I have copy_to working properly for exact matches but I am unable to properly set it up with partial matches. Below is my mappings/settings and query with expected and actual results.
settings:
{
"test": {
"settings": {
"index": {
"analysis": {
"filter": {
"ngram_filter": {
"type": "edge_ngram",
"min_gram": "1",
"max_gram": "15"
}
},
"analyzer": {
"ngram_analyzer": {
"filter": [
"lowercase",
"ngram_filter"
],
"type": "custom",
"tokenizer": "standard"
}
}
},
"number_of_shards": "1",
"number_of_replicas": "1",
}
}
}
}
mappings:
POST /test/_mapping/name
{
"name": {
"properties": {
"vital": {
"properties": {
"first": {
"type": "string",
"copy_to": "full_name",
"term_vector": "yes",
"analyzer": "ngram_analyzer",
"search_analyzer": "standard"
},
"last": {
"type": "string",
"copy_to": "full_name",
"term_vector": "yes",
"analyzer": "ngram_analyzer",
"search_analyzer": "standard"
},
"full_name": {
"type": "string",
"term_vector": "yes",
"analyzer": "ngram_analyzer",
"search_analyzer": "standard"
}
}
}
}
}
}
POST:
POST /test/name
{
"vital": {
"first": "Tom",
"last": "Doe"
}
}
Now when I do the search ...
GET /test/name/_search
{
"query": {
"match": {
"full_name": {
"query": "Tom Doe",
"operator": "and"
}
}
}
}
... I get back the result!! Hurrraaaay, but if I do the search ....
GET /test/name/_search
{
"query": {
"match": {
"full_name": {
"query": "Tom Do",
"operator": "and"
}
}
}
}
... I get back no result :( I would like partial matching to work for full_name as well. As another not I am successfully able to due partial matching on first and last name. It is just full_name that is not working. How would I go about this?
You have one little mistake in your mapping, you need to copy the first and last names into the vital.full_name
field, not just full_name
, otherwise that will create a new string field named full_name
with a standard analyzer at the top-level of your mapping (if you run GET test
you'll see that new field in your mapping):
POST /test/_mapping/name
{
"name": {
"properties": {
"vital": {
"properties": {
"first": {
"type": "string",
"copy_to": "vital.full_name", <--- fix this
"term_vector": "yes",
"analyzer": "ngram_analyzer",
"search_analyzer": "standard"
},
"last": {
"type": "string",
"copy_to": "vital.full_name", <--- fix this
"term_vector": "yes",
"analyzer": "ngram_analyzer",
"search_analyzer": "standard"
},
"full_name": {
"type": "string",
"term_vector": "yes",
"analyzer": "ngram_analyzer",
"search_analyzer": "standard"
}
}
}
}
}
}
And then fix your queries like this:
POST /test/name/_search
{
"query": {
"match": {
"vital.full_name": { <-- fix this
"query": "Tom Doe",
"operator": "and"
}
}
}
}
POST /test/name/_search
{
"query": {
"match": {
"vital.full_name": { <-- fix this
"query": "Tom Do",
"operator": "and"
}
}
}
}
Both will work as you expect.
Just drop "search_analyzer": "standard"
from you mappings, it's something required only in certain use cases, like autocomplete searches. See explanation here https://www.elastic.co/guide/en/elasticsearch/guide/master/_index_time_search_as_you_type.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With