Using NEST on ElasticSearch - How do i use a partially populated object as a search criteria

StackOverflow https://stackoverflow.com/questions/13317396

  •  28-11-2021
  •  | 
  •  

문제

So I have successfully created my index of "Package" objects and a straight forward text query is working perfectly.

I'd love to know if / how i can use a partially populated object (of type "Package") as the criteria for my search?

Packages looks something like:

var packages =  new List<Package> {
            new Package {
                Name = "Maverick",
                TargetBusiness = new Business {
                    Industry = "Retail",
                    BusinessType = BusinessType.Product,
                    LocationType = LocationType.Store
                },
                Description = "Standard package for retail shops"
            },
            new Package {
                Name = "Goose",
                TargetBusiness = new Business {
                    Industry = "Retail",
                    BusinessType = BusinessType.Product,
                    LocationType = LocationType.Online
                },
                Description = "Standard package for ecommerce shops"
            },
            new Package {
                Name = "Viper",
                TargetBusiness = new Business {
                    Industry = "Advertising",
                    BusinessType = BusinessType.Service,
                    LocationType = LocationType.Office
                },
                Description = "Standard package test retail"
            }
        }

query currently looks something like:

var result = client.Search<Package>(x => x.Query(q => q.QueryString(qs => qs.Query("q=retail"))));

But id like to have something like:

var result = client.Search<Package>(x => x.Query(q => q.Object(new Package{...etc ...})));

I hope I'm making sense :D Thanks in advance

도움이 되었습니까?

해결책

var result = client.Search<Package>(x => x.Query(q => q.Object(new Package{...etc ...})));

Can never work because Nest cannot infer what type of query to use for each property on your object, (i.e term, prefix, wildcard, query_string, etc etc etc).

In your example q=retail only works because elasticsearch will break the query up into q OR retail. You can target fields using regular lucene syntax i.e targetBusiness.industry:retail.

In elasticsearch if your querystring is not bound to a field it will by default search in the _all field which will have all the terms for all the properties of an object. Which is why if you really have a lot of data turning off _all support is usually a really good idea.

Nest doesn't currently have such a functionality where it can take a partially filled object and translate it into an elasticsearch query_string query.

Say if this is your query:

client.Search<Package>(s=>s
    .From(0)
    .Size(10)
    .Filter(f=>
        f.Term(p=>p.TargetBusiness.Industry, "Advertising")
        && f.Exists(p=>p.Name)
    )
    .Query(q=>
       q.QueryString(qs=>qs
           .Query("ecommerce")
           .Operator(Operator.and)
       )
    )
)

In the above example you'll have to create your own method that gives all the terms to search for in the query string query based on your package.

i.e

public string MyPackageQueryString(Package package) 
{
    var myTerms = List<string>();
    myTerms.Add(package.Name);
    if (package.TargetBusiness != null)
    {
        myTerms.Add(package.Industry)
        ....
    }
    ...
    return string.Join(" ", myTerms.Where(t=>!string.IsNullOrWhiteSpace(t)));
}

and then

client.Search<Package>(s=>s
    .From(0)
    .Size(10)
    .Filter(f=>
        f.Term(p=>p.TargetBusiness.Industry, "Advertising")
        && f.Exists(p=>p.Name)
    )
    .Query(q=>
       q.QueryString(qs=>qs
           .Query(this.MyPackageQueryString(package))
           .Operator(Operator.or)
       )
    )
)

다른 팁

That really helped put me on the right track - in the end that looked like a sort of cross search: Searching every field with every other field which i didn't want.

Ended up (possible incorrectly) going with:

return _searchClient.Search<Package>(s => s.Query(q => 
        q.Term("industry", criteriaPackage.TargetBusiness.Industry.ToLower()) ||
        q.Term("description", criteriaPackage.TargetBusiness.Description.ToLower()) ||
        q.Term("businessType",((int)criteriaPackage.TargetBusiness.BusinessType).ToString()) ||
        q.Term("locationType", ((int)criteriaPackage.TargetBusiness.LocationType).ToString()) ||
        q.Term("marketSegment", criteriaPackage.TargetBusiness.MarketSegment.ToLower()) ||
        q.Term("offer", criteriaPackage.TargetBusiness.Offer.ToLower()))
      ).Documents;

Which after a few unit tests seemed to be producing the results i was wanting.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top