0

I have multiple fields, eg. f1, f2, f3, that I want to search a single term against each and return the aggregated score where any field matches. I do not want to search each field by the same terms, only search a field by its own term, eg. f1:t1, f2:t2, f3:t3.

Originally, I was using a must bool query with multi_match and the fields all concatenated as t1 t2 t3 and all fields searched, but the results aren't great. Using a dis_max query gets better results where I'm able to search the individual fields by their own term, but if for example t1 is found in f1 AND t2 in f2 the results from dis_max give back the highest resulting score. So if I have 3 documents with { "f1": "foo", "f2": "foo" }, { "f1": "foo", "f2": "bar" }, { "f1": "foo", "f2": "baz" } and I search for f1:foo and f2:ba I can still get back the first record with f2 of foo in the case where it was created most recently. What I'm trying to do is say that f1 matched foo so there's a score related to that, and f2 matched bar so the resultant score should be f1.score + f2.score always bringing it up to the top because it matches both.

I'm finding that I could programmatically build a query that uses query_string, eg. (limiting to two fields for brevity)

GET /_search
{
  "query": {
    "query_string": {
      "query": "(f1:foo OR f1.autocomplete:foo) OR (f2:ba OR f2.autocomplete:ba)"
    }
  }
}

but I need to add a boost to the fields and this doesn't allow for that. I could also use a dis_max with a set of queries, but I'm really not sure how to aggregate score in that case.

Using better words, what I'm trying to search for is: if I have people data and I want to search for first name and last name, without searching first by last and last by first, a result that matches both first and last name should be higher than if it only returns one or the other.

Is there a better/good/proper way to achieve this using something? I feel like I've been over a lot of the query API and haven't found something that would be most good.

2 Answers 2

0

You can use a simple should query

 minimum_should_match:1,
 "should" : [
        { "term" : { "f1" : "foo" } },
        { "term" : { "f2" : "ba" } }
      ]

more clause a document matches , more score it will have.

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

3 Comments

This improves the scoring, but it only matches records that have both foo as f1 and ba as f2, I need to also match those which have only foo as f1 or ba as f2.
@geoffjay should clause is like "OR" . It will return a document even if only one of the condition matches
the query I was using wasn't including the autocomplete index, adding those in and making some minor changes got me where I need to be. Thanks.
0

Unable to edit the answer provided so posting the solution that was derived from the other answer here.

GET _search
{
  "query": {
    "bool": {
      "minimum_should_match": 1,
      "should": [
        {
          "match": {
            "f1": {
              "query": "foo",
              "boost": 1.5
            }
          }
        },
        {
          "match": {
            "f1.autocomplete": {
              "query": "foo",
              "boost": 1.5
            }
          }
        },
        {
          "match": {
            "f2": {
              "query": "ba",
              "boost": 1
            }
          }
        },
        {
          "match": {
            "f2.autocomplete": {
              "query": "ba",
              "boost": 1
            }
          }
        }
      ]
    }
  }
}

This gets me results that meet all of my criteria.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.