Поиск по строке запроса через пробел в разных полях - PullRequest
0 голосов
/ 05 февраля 2020

Вот мой пример набора проиндексированных объектов. Допустим, он представляет собой набор заказов Покупателей.

[
    {
        "Id": 1,
        "Product": "Peugeot",
        "Customer": "John Woo"
    },
    {
        "Id": 2,
        "Product": "Peugeot",
        "Customer": "John Carpenter"
    },
    {
        "Id": 3,
        "Product": "Peugeot",
        "Customer": "Bruce Lee"
    },
]

Обратите внимание, что все они «Пежо», но Клиенты разные: есть два «Джона» и один «Брюс Ли».

Вот моя строка запроса: 'Peugeot John'

Чего я хочу от Elasti c, так это вернуть все продукты Peugeot, заказанные клиентами, с именем John в именах. Что означает следующий результат:

[
    {
        "Id": 1,
        "Product": "Peugeot",
        "Customer": "John Woo"
    },
    {
        "Id": 2,
        "Product": "Peugeot",
        "Customer": "John Carpenter"
    }
]

Обратите внимание, что сущность с Id = 3 должна быть пропущена, поскольку клиент - «Брюс Ли». Таким образом, каждое слово в строке запроса должно применяться ко всему объекту, а не к каждому полю последовательно.

Поэтому я запускаю свой запрос "multi_match", используя библиотеку NEST C#:

elasticClient.SearchAsync<OrderModel>(descriptor => 
    descriptor
        .Index("myIndex")
        .Size(20)
        .Query(q => q
            .MultiMatch(m => m
                .Fields(f => f
                    .Fields(
                        p => p.Product,
                        p => p.Customer
                    )
                )
                .Operator(Operator.And)
                .Query("Peugeot John")
            )
        )
)

Ничего не возвращает Потому что он разбивает запрос на два слова: «Peugeot» и «John» и применяет их к каждому полю с помощью оператора AND. Поскольку нет полей со значениями, которые содержат «Peugeot» и «John» вместе, результат будет пустым.

Когда я изменяю оператор на ИЛИ, поведение по-прежнему некорректно: он возвращает все 3 объекта, потому что все они совпадают Слово «Peugeot».

Так как же мне добиться такого же поведения, как «поиск по всему объекту с разделителями по запросу»?

Спасибо.

1 Ответ

2 голосов
/ 05 февраля 2020

Похоже, хорошо подходит для cross_field типа запроса с несколькими совпадениями

var results = await client.SearchAsync<Document>(s => s
    .Query(q => q.MultiMatch(m => m
        .Fields(f => f.Fields("product", "customer"))
        .Type(TextQueryType.CrossFields)
        .Operator(Operator.And)
        .Query(query))));

Вывод:

Results for query "Peugeot John":
Peugeot - John Woo
Peugeot - John Carpenter
...