2

I need to query an ElasticSearch index through the Python module and I am pretty unfamiliar with ElasticSearch. Say my index stores pairs of persons and some information about each pair. I wonder how to create an ElasticSearch query which would give me below pair. Basically, I want to get the some info field value from the pair where person1 is named John White and a teacher and person2 is named Sarah Black and a doctor. I want an exact match, not a fuzzy one.

"person1": {
    "name": "John White",
    "job": "teacher"

}
"person2": {
    "name": "Sarah Black",
    "job": "doctor"
}
"some info": "blah blah"

I tried below query but it gives me pairs where only 1 of the pairs matches the info I ask for, the other person's name/job could be very different. How to get an exact match where both persons' info matches?

  "query": {
    "bool" : {
        "must": {
            "bool" : {
                "should": [
                    { "match": { "person1.name": "John White" }},
                    { "match": { "person1.job": "teacher" }}
                  ],
                "should": [
                    { "match": { "person2.name": "Sarah Black" }},
                    { "match": { "person2.job": "doctor" }}
                  ]
            }
        }
    }
  }
4
  • Use .keyword for name and job. It will return the exact match. I mean person1.name.keyword likewise for the others too. Commented Sep 21, 2019 at 21:03
  • it did not resolve the problem. the hit count reduced from 400 to 100, but I still get pairs where only one person's info matches.. Commented Sep 21, 2019 at 21:08
  • Add your index mapping above. Commented Sep 21, 2019 at 21:26
  • I have updated my answer for your use case. Do check and let me know. Commented Sep 21, 2019 at 22:30

1 Answer 1

1

Try like this

Mapping for your index

{
  "settings": {
    "analysis": {
      "normalizer": {
        "lc_normalizer": {
          "type": "custom",
          "filter": ["lowercase"]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "person1": {
        "properties": {
          "name": {
            "type": "text",
            "fields": {
              "exact": {
                "type": "keyword",
                "normalizer": "lc_normalizer"
              }
            }
          },
          "job": {
            "type": "keyword"
          }
        }
      },
      "person2": {
        "properties": {
          "name": {
            "type": "text",
            "fields": {
              "exact": {
                "type": "keyword",
                "normalizer": "lc_normalizer"
              }
            }
          },
          "job": {
            "type": "keyword"
          }
        }
      },
      "some_info": {
        "type": "text"
      }
    }
  }
}

Query

{
  "query": {
    "bool": {
      "must": [
        {"match": {
          "person1.name.exact": "john white"
        }},
        {"match": {
          "person2.name.exact": "Sarah Black"
        }},
        { "term": { "person1.job": "teacher"}},
        { "term": { "person2.job": "doctor"}}
      ]
    }
  }
}

Hope it helps

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

2 Comments

Thanks, this works! A followup question: What is the difference between using term vs. using match with exact?
Term is case-sensitive. Match query is not case-sensitive. That's the actual difference.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.