Exact match for string field

Hello,

Can anyone help me to find out how we can get exact search term match using query?
I have two field in my index.

  1. contentid
  2. Title

So if i provide full value for contentid and title in query so it should give me exact match. Like we use "" around to get phrase search.

Guide me!!!!

Regards,
Priyanka

  1. Create an index with an explicit mapping.
  2. Make each field which needs to answer exact string searches a Keyword field

Titles are an unusual choice for a keyword field. Isn't contentid already unique per record? Even if I had to sometimes search by title, I would usually only search for contentid or title in any one query.

Still, if you really want exact string matches for both, make them both keyword fields and then issue Term queries on them.

Finally, a more flexible mapping would be to allow title to be used both for searching for individual words, and full exact matches. This also takes up more space. If you only ever want exact string matches, delete the fields part of the title mapping.

{
  "mappings": {
    "properties": {
      "contendid": {
        "type":  "keyword"
      },
      "title": {
        "type":  "text",
        "fields": {
          "raw": { 
            "type":  "keyword"
          }
        }
      }
    }
  }
}

With that mapping, issue Term queries to contentid and title.raw, but issue any of the full text queries to title (simplest are Match and Query String).

Hello @Emanuil,

I want to change mapping of my index.
Is that possible? If yes them how i can achieve that ?

I was trying to change mapping for contentid and title. but it is giving me an error:

{
  "mappings": {
    "properties": {
      "contendid": {
        "type":  "keyword"
      },
      "title": {
        "type":  "text",
        "fields": {
          "raw": { 
            "type":  "keyword"
          }
        }
      }
    }
  }
}

Error:

{
  "error": {
    "root_cause": [
      {
        "type": "resource_already_exists_exception",
        "reason": "index [content/JwC7RMkFQ6GUhc3thRmPDw] already exists",
        "index_uuid": "JwC7RMkFQ6GUhc3thRmPDw",
        "index": "content"
      }
    ],
    "type": "resource_already_exists_exception",
    "reason": "index [content/JwC7RMkFQ6GUhc3thRmPDw] already exists",
    "index_uuid": "JwC7RMkFQ6GUhc3thRmPDw",
    "index": "content"
  },
  "status": 400
}

Regards,
Priyanka

Mappings can't always be changed after data has been indexed. Usually this is dealt with by creating a new index with the desired mappings. Are you able to do that and switch to using a new index once the data is moved?

  1. Create a new index using the new mapping
  2. Reindex your data. One option is to repeat whatever external process you had for ingesting the data in the first place. Alternatively, you can reindex within Elasticsearch once the new index with the new mapping has been set up.

Hello @Emanuil,

I have created new index with new mappings and then re indexed that with old index.
and now i am trying to apply that in my search query. but it is not giving me any results.
My query uses aggregations and within that i have used query with bool and match_all.

Regards,
Priyanka

I know you just defined a mapping but can you paste the output of retrieving your mapping just to check it's applied properly? (Open browser at /your_index/_mapping.)

If you could also paste 1 sample document which should not be matched by the query, 1 sample which should be matched, and the query itself, that'd be grand.

Hello @Emanuil,

Please find mapping for my title :

  "title" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }

Mapping for my contentid:
"contentid" : {
"type" : "long"
}

and query sample where i want to use title and contentid for exact match :

{
   "from": "1",
   "size": "10",
   "aggs": {
      "content_type": {
         "terms": {
            "field": "content_type.keyword",
            "size": 50
         }
      },
      "content_subtype": {
         "terms": {
            "field": "content_subtype.keyword",
            "size": 100
         }
      },
      "helpdeskname": {
         "terms": {
            "field": "helpdeskname.keyword",
            "size": 20
         }
      },
      "keywords": {
         "terms": {
            "field": "keywords",
            "size": 10
         }
      },
      "segmentname": {
         "terms": {
            "field": "segmentname.keyword",
            "size": 10
         }
      },
      "category": {
         "terms": {
            "field": "category_paths.keyword",
            "size": 10
         }
      },
      "category_name": {
         "terms": {
            "field": "category_name.keyword",
            "size": 5000
         }
      },
      "template_field": {
         "terms": {
            "field": "template_field.keyword",
            "size": 100
         }
      },
      "scope": {
         "terms": {
            "field": "scope.keyword",
            "size": 10
         }
      },
      "lastmodified_year": {
         "terms": {
            "field": "lastmodified_year",
            "size": 20,
            "order": {
               "_key": "asc"
            }
         }
      },
      "submitted_year": {
         "terms": {
            "field": "submitted_year",
            "size": 30,
            "order": {
               "_key": "asc"
            }
         }
      }
   },
   "query": {
      "bool": {
         "must": [
            {
               "terms": {
                  "event": [
                     "update",
                     "new"
                  ]
               }
            },
            {
               "terms": {
                  "business_line": [
                     "3"
                  ]
               }
            },
            {
               "terms": {
                  "status": [
                     "12"
                  ]
               }
            },
            {
               "multi_match": {
                  "query": "oil",
                  "fields": [
                     "contentid^15",
                     "title^14",
                     "object_summary^13",
                     "keywords^12",
                     "content_type^11",
                     "content_subtype^10",
                     "ref_page_data^9",
                     "primary_mnemonic^8",
                     "secondary_mnemonic^7",
                     "quest_ids^6",
                     "template_field^5",
                     "submitted_for_name^4",
                     "content_authors^3",
                     "action_by^2",
                     "category_paths"
                  ]
               }
            },
            {
               "terms": {
                  "segmentid": [
                     "18252"
                  ]
               }
            }
         ],
         "must_not": {
            "match": {
               "scope": "Local"
            }
         }
      }
   }
}

Regards,
Priyanka

Hey, unfortunately I can't recreate your examples locally right now. Just noting that a Term query is usually used for exact matches, like your segmentid query. I would do contentid similarly to segmentid.

Title:

  • if you really want to match titles exactly, move title out of the match query into a term query and use title.keyword as the field name
  • otherwise if you'd like to search it as analysed text, leave it where it is

Hello @Emanuil,

I can use contentid in terms but when i am doing this i am not getting any results.
And if i remove aggs and multi_match, It will start working.
I want to run my query with aggs and multi_match.
Is that possible?

Regards,
Priyanka

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.