запрос elasticsearch также соответствует терминам, в которых есть тире.

У меня есть запрос, аналогичный приведенному ниже

{
    "size": 15,
    "from": 0,
    "query": {
        "filtered": {
            "filter": {
                "bool": {
                    "must": [
                        {
                            "match_phrase": {
                                "category": "men_fashion"
                            }
                        },
                        {
                            "match_phrase": {
                                "category": "western_clothing"
                            }
                        },
                        {
                            "match_phrase": {
                                "category": "shirts"
                            }
                        }
                    ]
                }
            }
        }
    }

Проблема здесь в том, что он также извлекает товары из категории «футболки». Как я могу ограничить это, чтобы найти только точные совпадения?

ОБНОВЛЕНИЯ: вот код, который я использую для сопоставления

{
    "mappings": {
        "products": {
            "properties": {
                "variations": {
                    "type": "nested"
                }
            }
        }
    }
}

Вот реальный образец продукта

{
    "title": "100% Cotton Unstitched Suit For Men",
    "slug": "100-cotton-unstitched-suit-for-men",
    "price": 200,
    "sale_price": 0,
    "vendor_id": 32,
    "featured": 0,
    "viewed": 20,
    "stock": 4,
    "sku": "XXX-B",
    "rating": 0,
    "active": 1,
    "vendor_name": "vendor_name",
    "category": [
        "men_fashion",
        "traditional_clothing",
        "unstitched_fabric"
    ],
    "image": "imagename.jpg",
    "variations": [
        {
            "variation_id": "34",
            "stock": 5,
            "price": 200,
            "variation_image": "",
            "sku": "XXX-C",
            "size": "m",
            "color": "red"
        },
        {
            "variation_id": "35",
            "stock": 5,
            "price": 200,
            "variation_image": "",
            "sku": "XXX-D",
            "size": "l",
            "color": "red"
        }
    ]
}

person omer Farooq    schedule 07.09.2017    source источник
comment
В большинстве случаев это проблема отображения. Не могли бы вы дополнить свой вопрос некоторыми образцами документов? Если категория представляет собой поле массива, вы, вероятно, могли бы решить эту проблему, просто используя сопоставление ключевых слов, поскольку эти значения выглядят как фиксированные строки, которые не требуют анализа.   -  person Andreas Jägle    schedule 10.09.2017


Ответы (1)


Вы не предоставили никакой информации о своем сопоставлении, поэтому я предполагаю, что у вас есть стандартный анализатор, примененный к полю category. Глядя на ваш запрос (синтаксис фильтра), я также предполагаю, что вы работаете с версией ES ниже 5.0.

В стандартном анализаторе при индексации t-shirt документов создаются следующие термины для поля category:

http://127.0.0.1:9200/_analyze?analyzer=standard&text=t-shirt
{
    "tokens": [
        {
            "token": "t",
            "start_offset": 0,
            "end_offset": 1,
            "type": "<ALPHANUM>",
            "position": 0
        },
        {
            "token": "shirt",
            "start_offset": 2,
            "end_offset": 7,
            "type": "<ALPHANUM>",
            "position": 1
        }
    ]
}

Итак, теперь, когда вы ищете shirts, вы также получаете t-shirts документов.

Если поле category в вашем варианте использования не удалось проанализировать (вам не нужен полнотекстовый поиск), то просто пометьте поле category как not_analyzed.

{
    "mappings": {
        "data": {
            "properties": {
                "category": {
                    "type":     "string",
                    "index":    "not_analyzed"
                }
            }
        }
    }
}

Если вам нужно сохранить возможность анализа контента category, вы можете использовать Анализатор пробелов (дефис не будет рассматриваться как разделитель слов):

{
    "mappings": {
        "data": {
            "properties": {
                "category": {
                    "type": "string",
                    "analyzer": "whitespace"
                }
            }
        }
    }
}

Другим решением является использование анализатора ключевых слов но это будет похоже на not_analyzed вариант.

Все зависит от ваших потребностей, но все решения требуют изменения отображения вашего индекса. Вы можете проверить поведение анализатора с помощью:

http://127.0.0.1:9200/_analyze?analyzer=whitespace&text=t-shirt
http://127.0.0.1:9200/_analyze?analyzer=keyword&text=t-shirt
http://127.0.0.1:9200/_analyze?analyzer=standard&text=t-shirt

Дополнительная информация

В основном вы ищете в поле category, поэтому тот факт, что variations вложен, здесь не важен. Поле category с типом string может содержать массив значений, тут тоже не проблема.

С этим сопоставлением (примечание "analyzer": "whitespace"):

PUT http://localhost:9200/test
{
    "mappings": {
        "products": {
            "properties": {
                "variations": {
                    "type": "nested",
                    "properties": {
                        "size":    { "type": "string" },
                        "color":   { "type": "string" },
                        ... // other nested fields
                    }
                },
                "category":    { 
                    "type": "string",
                    "analyzer": "whitespace"
                },
                ... // other fields
            }
        }
    }
}

Я проиндексировал два документа

Документ 1:

{
    "category": [
        "men_fashion",
        "traditional_clothing",
        "unstitched_fabric",
        "shirts"
    ],
    "image": "imagename.jpg",
    "variations": [
        {
            "variation_id": "34",
            "stock": 5,
            "price": 200,
            "variation_image": "",
            "sku": "XXX-C",
            "size": "m",
            "color": "red"
        }
    ]
}

Документ 2:

{
    "category": [
        "men_fashion",
        "traditional_clothing",
        "unstitched_fabric",
        "t-shirts"
    ],
    "image": "imagename.jpg",
    "variations": [
        {
            "variation_id": "34",
            "stock": 5,
            "price": 200,
            "variation_image": "",
            "sku": "XXX-C",
            "size": "m",
            "color": "red"
        },
        {
            "variation_id": "35",
            "stock": 5,
            "price": 200,
            "variation_image": "",
            "sku": "XXX-D",
            "size": "l",
            "color": "red"
        }
    ]
}

Теперь, когда я ищу с помощью:

{
    "size": 15,
    "from": 0,
    "query": {
        "filtered": {
            "filter": {
                "bool": {
                    "must": [
                        {
                            "match_phrase": {
                                "category": "men_fashion"
                            }
                        },
                        {
                            "match_phrase": {
                                "category": "shirts"
                            }
                        }
                    ]
                }
            }
        }
    }
}

Я получаю только документ 1.

Вы можете добавить "analyzer": "whitespace" также во вложенное поле variations.color и т. д. аналогичным образом, если вам нужно (но поисковый запрос также должен быть изменен для поиска по вложенным документам).

person Joanna    schedule 11.09.2017
comment
Джоанна, спасибо, моя карта немного отличается от вашей. Я обновил свой ответ кодом, который я использую для сопоставления. Пожалуйста, посмотрите - person omer Farooq; 14.09.2017
comment
Поле category находится внутри поля variations, чтобы у вас был документ типа { "variations": { "category" : "t-shirts", "otherField": "..." } }? Я спрашиваю, потому что не вижу в вашем запросе вложенного синтаксиса. Если нет, опубликуйте упрощенную версию документа и версию Elasticsearch, с которой вы работаете. Я постараюсь проверить это. - person Joanna; 14.09.2017