Query with multiple terms

Let's assume I am looking for the following terms: A, B and C.

How can I structure a query so I get:

  • First all documents containing (A AND B AND C)
  • Then, all documents containing (A AND B) OR (A AND C) OR (B AND C)
  • And last, documents containing (A OR B OR C)

For Example if I am looking for: Strawberry Chocolate Cake, I'd like to get:

  • First, recipes for Strawberry Chocolate Cakes
  • Then, recipes for Strawberry Cakes, Chocolate Cakes and Chocolate Strawberries
  • And last, recipes about Strawberries, or Cholocolate, or Cake.

I am not sure how to structure such a query (ideally in C# / .NET)

What you are describing should naturally happen. Lucene is the search engine that underpins elasticsearch and it uses the following heuristics when searching:

  1. Docs containing all of the provided search terms are better than those with few
  2. Docs that mention the terms multiple times are better than those with only one.
  3. Shorter documents are better than very long ones.
  4. Matches on rare search terms are better than those only matching common terms.

These ranking factors have names (coord, TF, length norm, IDF) and the scores can be seen using the explain api [1]

Presumably "strawberry chocolate cake" is something an end user types in so the question is how to take that string and turn it into some JSON elasticsearch can run with. The answer is there are several options and you don't have to settle on one. You could, for example, express it as a logical query "a OR b OR c" but also simultaneously run it as a phrase "a NEXTTO b NEXTTO c" (this is pseudo code). The first query is very lax, matching any of the given words while the second is very strict and needs all the words in that exact order. Of course documents that match both of these query clauses will score more highly than those that match only one.

The lax and tight query clauses are nested in a bool expression as elements in a should array :

POST test/_search
{
   "query": {
	  "bool": {
		 "should": [
			{
			   "match": {
				  "recipe": "strawberry chocolate cake"
			   }
			},
			{
			   "match_phrase": {
				  "recipe": "strawberry chocolate cake"
			   }
			}
		 ]
	  }
   }
}

[1] https://www.elastic.co/guide/en/elasticsearch/guide/2.x/relevance-intro.html#explain-api

This is very clear, thanks a lot!