skip to Main Content

I’m new to Elasticsearch. I’m faced with unexpected behaviour with my client’s search page result and my investigation has ended up in the ES structure.

I have a document field name, which has this mapping:

"name": {
    "type": "text",
    "fields": {
        "sort_name": {
            "index": false,
            "type": "keyword"
        }
    }
}

So, usually, it has one value, so in this case, it matches a query correctly. But sometimes I have a document, which has an array of product names, which leads to fetching all of the array values into the search page result.

For example, if I have a product, which looks like this:

{
    ...,
    "name": [
        "Tesla",
        "Model",
        "XXX"
    ]
}

So, when I search this on name:

{
    "from": 0,
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "name": "Tesla"
                    }
                }
            ]
        }
    },
    "size": 150,
    "sort": [
        {
            "_score": {
                "order": "desc"
            }
        }
    ],
    "stored_fields": [
        "_id",
        "_score"
    ]
}

It returns this:

"hits": {
    "total": 1,
    "max_score": 1.0,
    "hits": [
        {
            "_index": "magento2_product_4_v2",
            "_type": "document",
            "_id": "99999",
            "_score": 1.0,
            "_source": {
                "name": [
                    "Tesla",
                    "Model",
                    "XXX"
                ]
            }
        }
    ]
}

When I needed only Tesla.

As a result, I will have 2 different products (imagine that Model and XXX are products), that users didn’t search.

I would really want to avoid structure changes if that’s possible since the new index is created automatically during reindex process (I’m using Magento 2 right now), so could you help me with the query?

2

Answers


  1. You have 1 document in your index magento2_product_4_v2.
    This is

    {
        ...,
        "name": [
            "Tesla",
            "Model",
            "XXX"
        ]
    }
    

    after request you get this document because this doc suits your request.

    May be you want create 3 docs?

    {
        ...,
        "name": [
            "Tesla",
        ]
    } 
    
    
    {
        ...,
        "name": [
            "Model"
        ]
    }
    
    
    {
        ...,
        "name": [
            "XXX"
        ]
    }
    
    
    Login or Signup to reply.
  2. There is no way to do this in elasticsearch without changing the mapping. You have a few options. such as using a nested or object field type.
    You can also simply postprocess the results with regex, depending on how many ES features you’re using to get the match in the first place.

    Here is a potential mapping that you could use, assuming you know which specific field you want to search on.

    "name": {
        "type": "object",
        "properties": {
            "make": {
                "type": "keyword"
            },
            "model": {
                "type": "keyword"
            },
            "trim": {
                "type": "keyword"
            }
        }
    }
    

    Then you could write a query like this:

    {
       "match": {
            "name.make": "Tesla"
       }
    }
    

    However, depending on the mapping and the data, this can not be enough in many cases, for example with arrays, due to the way elasticsearch flattens objects at index time. The other option would be to use a nested field type, which can ding performance on the search side. To me, this sounds like something that warrants revisiting the data modeling/es mapping side of things to get the search functionality you’re looking for. Read more on the nested mapping type here.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search