1
votes

I have a query looking like this:

((company_id:1) AND (candidate_tags:"designer"))

However this also matches users where candidate_tags is interaction designer. How do I exclude these?

Here's my full search body:

{
    "query": {
        "filtered": {
            "query": {
                "query_string": {
                    "query":
                        "((company_id:1) AND (candidate_tags:\"designer\"))"
                }
            }
        }
    }
    "sort":{
        "candidate_rating":{
            "order":"desc"
        },
        "candidate_tags",
        "_score"
    }
}

Extra info

Realised now that an answer came in: candidate_tags is an array of strings, and say, a candidate has the tags interaction designer and talent, searching for talent should be a match but designer should not.

3
Make your candidate_tags field as not_analyzed or analyzed with keyword analyzer.Andrei Stefan

3 Answers

2
votes

Make your candidate_tags field as not_analyzed or analyzed with keyword analyzer.

{
  "mappings": {
    "test": {
      "properties": {
        "candidate_tags": {
          "type": "string",
          "index": "not_analyzed"
        }
      }
    }
  }
}

or add a raw field to your existent mapping like this:

{
  "mappings": {
    "test": {
      "properties": {
        "candidate_tags": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        }
      }
    }
  }
}

For the first option use the same query as you use now. For the second option use candidate_tags.raw, like this:

{
  "query": {
    "filtered": {
      "query": {
        "query_string": {
          "query": "((company_id:1) AND (candidate_tags.raw:\"designer\"))"
        }
      }
    }
  }
...
0
votes

Another way is to use script:

POST test/t/1
{
"q":"a b"
}
POST test/t/2
{
  "q":"a c"
}
POST test/t/_search
{
"query": {
    "filtered": {
    "filter": {
        "script": {
        "script": "return _source.q=='a b'"

     }
     }
  }
 }  
}
0
votes
  1. By filtering.
  2. By making field candidate_tags an exact-value field - aka not_analyzed field (Andrei Stefan's solution, answered above)

With #2 be careful that you don't later mix the field that is not_analyzed with those that are. More: https://www.elastic.co/guide/en/elasticsearch/guide/current/_exact_value_fields.html

With #1, your query would look something like that (written from memory, don't have ES on me so can't verify):

{
    "query": {
        "filtered": {
            "query": {
                "query_string": {
                    "query":
                        "((company_id:1) AND (candidate_tags:\"designer\"))"
                }
            },
            "filter" : {
                "term" : { 
                    "candidate_tags" : "designer"
                }
            }
        }
    }
    "sort":{
        "candidate_rating":{
            "order":"desc"
        },
        "candidate_tags",
        "_score"
    }
}