0

I have this elasticsearch query, that works perfect in a raw format and I am having trouble turning it into a C# NEST clause.

This is the raw query:

{  
"query":{  
      "constant_score":{  
         "filter":{  
            "bool":{  
               "must":{  
                  "term":{  
                     "ingredients":"baking"
                  }
               },
               "must":{  
                  "term":{  
                     "ingredients":"soda"
                  }
               }
            }
         }
      }
   }
}

And this is what I thought would work in C# NEST:

public List<Recipe> FindByMultipleValues(string field, string[] values) {
        List<string> vals = values.ToList();
        return client.Search<Recipe>(s => s
            .Query(q => q
                .Bool(fq => fq
                    .Filter(f => f
                        .Term(rec => rec.Ingredients, vals)
                    )
                )
            )
        ).Documents.ToList();
    }

The user can send an array of x values, which means that for each value there must be a:

"must":{  
    "term":{  
        "ingredients":"soda"
         }
     }
2
  • the must clause of a bool query is an array; I would suspect that the second must clause property will end up overwriting the first. What version of NEST are you using? Commented Jul 23, 2016 at 3:17
  • I am using the latest version. 2.3.x I think it is. Commented Jul 23, 2016 at 8:17

1 Answer 1

1

Something like this will work

var terms = new[] { "baking", "soda" };

client.Search<Recipe>(s => s
    .Query(q => q
        .ConstantScore(cs => cs
            .Filter(csf => 
            {
                var firstTerm = csf.Term(f => f.Ingredients, terms.First());        
                return terms.Skip(1).Aggregate(firstTerm, (query, term) => query && csf.Term(f => f.Ingredients, term));
            })
        )
    )
);

will yield

{
  "query": {
    "constant_score": {
      "filter": {
        "bool": {
          "must": [
            {
              "term": {
                "ingredients": {
                  "value": "baking"
                }
              }
            },
            {
              "term": {
                "ingredients": {
                  "value": "soda"
                }
              }
            }
          ]
        }
      }
    }
  }
}

This takes advantage of operator overloading for QueryContainer that allows them to be &&'ed together to form a bool query with must clauses.

Sign up to request clarification or add additional context in comments.

3 Comments

That code will not run. It seems like it can't run the term f => f.Ingredients because it can't find ingredients.
The example assumes you have a POCO type called Recipe with a property named Ingredients. You'll need to adjust it accordingly to your model
Found out what you ment. Thanks for the help. It worked great!