How to do && and || job building queries in NEST?

According to http://nest.azurewebsites.net/concepts/writing-queries.html , && & and || operators can be used to combine two queries using the NEST library to communicate with Elastic Search.

I have the following request installed:

var ssnQuery = Query<NameOnRecordDTO>.Match( q => q.OnField(f => f.SocialSecurityNumber).QueryString(nameOnRecord.SocialSecurityNumber).Fuzziness(0) ); 

which is then combined with a Bool request, as shown below:

 var result = client.Search<NameOnRecordDTO>( body => body.Query( query => query.Bool( bq => bq.Should( q => q.Match( p => p.OnField(f => f.Name.First) .QueryString(nameOnRecord.Name.First).Fuzziness(fuzziness) ), q => q.Match(p => p.OnField(f => f.Name.Last) .QueryString(nameOnRecord.Name.Last).Fuzziness(fuzziness) ) ).MinimumNumberShouldMatch(2) ) || ssnQuery ) ); 

I think this query means that if SocialSecurityNumber or both the Name.First and Name.Last , then the record should be included in the results.

When I execute this query with the following data for the nameOnRecord object used in QueryString calls:

 "socialSecurityNumber":"123456789", "name" : { "first":"ryan", } 

The result is a person with SSN 123456789 , together with someone named ryan .

If I remove || ssnQuery || ssnQuery from the above query, I will get everyone whose name will be "ryan".

Using || ssnQuery || ssnQuery and the following query:

 { "socialSecurityNumber":"123456789", "name" : { "first":"ryan", "last": "smith" } } 

It seems I am getting a person with SSN 123456789 along with people whose first name is 'ryan' or their last name is 'smith'.

So it doesn't seem that adding || ssnQuery || ssnQuery has the effect that I expected, and I do not know why.

Here is the definition of the index on the object in question:

 "nameonrecord" : { "properties": { "name": { "properties": { "name.first": { "type": "string" }, "name.last": { "type": "string" } } }, "address" : { "properties": { "address.address1": { "type": "string", "index_analyzer": "address", "search_analyzer": "address" }, "address.address2": { "type": "string", "analyzer": "address" }, "address.city" : { "type": "string", "analyzer": "standard" }, "address.state" : { "type": "string", "analyzer": "standard" }, "address.zip" : { "type" : "string", "analyzer": "standard" } } }, "otherName": { "type": "string" }, "socialSecurityNumber" : { "type": "string" }, "contactInfo" : { "properties": { "contactInfo.phone": { "type": "string" }, "contactInfo.email": { "type": "string" } } } } } 

I do not think that the definition of the address analyzer is important, because the address fields are not used in the request, but can include it if someone wants to see it.

+3
source share
1 answer

Actually it was a mistake in NEST

A predecessor of how NEST helps translate logical queries:

NEST allows you to use operator overloading to create detailed bool queries / filters. i. ru:

term && term will result in:

 bool must term term 

A naive implementation of this will rewrite

term && term && term to

 bool must term bool must term term 

As you can imagine, this gets cumbersome pretty quickly, a more complex request becomes NEST, which can identify them and combine them to become

 bool must term term term 

Similarly, term && term && term && !term just becomes:

 bool must term term term must_not term 

now if in the previous example you go into booleanquery right like this:

bool(must=term, term, term) && !term

it will still generate the same request. NEST will also do the same with should when it sees that the logical descriptors in the game ONLY consist of should clauses . This is because boolquery does not exactly match the logic that you expect from a programming language.

To summarize the latter:

term || term || term

becomes

 bool should term term term 

but

term1 && (term2 || term3 || term4) will NOT

 bool must term1 should term2 term3 term4 

This is due to the fact that, as soon as a logical request has a prerequisite, it should begin to act as a factor of increase. Thus, in the previous case, you could get results that ONLY contain term1 , this is clearly not what you want in the strict logical sense of the input.

NEST rewrites this request to

 bool must term1 bool should term2 term3 term4 

Now that the error has entered the game, it was that you have your situation

bool(should=term1, term2, minimum_should_match=2) || term3 bool(should=term1, term2, minimum_should_match=2) || term3 NEST, identified by both sides of the OR operation, contains only meaningful sentences, and it combines them together, which would give different meaning to the minimum_should_match parameter of the first boolean request.

I just clicked the fix for this and it will be fixed in the next version 0.11.8.0

Thanks for catching this one!

+13
source

Source: https://habr.com/ru/post/973570/


All Articles