Elasticsearch запрос и сортировка по параметрам - PullRequest
0 голосов
/ 01 июня 2018

Как я могу запросить и отсортировать текст по указанному ниже параметру вasticsearch

1 - поисковый запрос будет точным в первой части результатов

2 - поисковый запрос будет точным в другой частирезультат

3 - результаты содержат все слова поискового запроса

Например:

При поиске: i love dogs

Результаты соответственно должны быть:

1-  I love dogs

2 - i love dogs and birds

3 - birds good but i love dogs and horses 

4 - Horses and i love dogs

5 - I love horses and dogs

6 - good dogs and i love horses

Ответы [ 2 ]

0 голосов
/ 03 июня 2018

Можно добиться желаемого поведения, но это потребует некоторой настройки вашего отображения и запроса.

Чтобы сократить историю, вот рабочий запрос

Во-первых,Вот отображение:

PUT my_phrase_search
{
  "mappings": {
    "doc": {
      "properties": {
        "expected_position": {
          "type": "long"
        },
        "my_phrase": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256,
              "normalizer": "my_normalizer"
            }
          }
        }
      }
    }
  },
  "settings": {
    "index": {
      "analysis": {
        "normalizer": {
          "my_normalizer": {
            "filter": [
              "lowercase"
            ],
            "type": "custom"
          }
        }
      }
    }
  }
}

Примечание. Я добавил поле expected_position, чтобы упростить оценку результатов.

Теперь запрос:

POST my_phrase_search/doc/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "should": [
              {
                "prefix": {
                  "my_phrase.keyword": "i love dogs"
                }
              }
            ],
            "_name": "prefix",
            "boost": 2
          }
        },
        {
          "bool": {
            "should": [
              {
                "match": {
                  "my_phrase": "i love dogs"
                }
              }
            ],
            "_name": "match"
          }
        },
        {
          "bool": {
            "should": [
              {
                "match_phrase": {
                  "my_phrase": "i love dogs"
                }
              }
            ],
            "_name": "phrase",
            "boost": 2
          }
        }
      ]
    }
  }
}

Thisдает следующие результаты:

[
  {
    "_score": 4.015718,
    "_source": {
      "my_phrase": "I love dogs",
      "expected_position": 1
    },
    "matched_queries": [
      "match",
      "phrase",
      "prefix"
    ]
  },
  {
    "_score": 3.233316,
    "_source": {
      "my_phrase": "i love dogs and birds",
      "expected_position": 2
    },
    "matched_queries": [
      "match",
      "phrase",
      "prefix"
    ]
  },
  {
    "_score": 1.3836111,
    "_source": {
      "my_phrase": "birds good but i love dogs and horses ",
      "expected_position": 3
    },
    "matched_queries": [
      "match",
      "phrase"
    ]
  },
  {
    "_score": 1.2333161,
    "_source": {
      "my_phrase": "Horses and i love dogs",
      "expected_position": 4
    },
    "matched_queries": [
      "match",
      "phrase"
    ]
  },
  {
    "_score": 0.8630463,
    "_source": {
      "my_phrase": "I love horses and dogs",
      "expected_position": 5
    },
    "matched_queries": [
      "match"
    ]
  },
  {
    "_score": 0.38110584,
    "_source": {
      "my_phrase": "good dogs and i love horses",
      "expected_position": 6
    },
    "matched_queries": [
      "match"
    ]
  }
]

Вы можете спросить, как это работает?Все ли эти изменения необходимы?Давайте выясним.

Что если мы просто используем поле text и запрос match?

Запрос match будет выглядеть так:

POST my_phrase/doc/_search
{
  "query": {
    "match": {
      "my_phrase": "i love dogs"
    }
  }
}

Это даст нам следующий порядок результатов: 5 - 1 - 3 - 2 - 4 - 6.

Вопрос в том, почему запрос для "i love dogs" не дал идеального совпадения, 1- I love dogs, так какпервый результат?Почему 5 - I love horses and dogs пришел первым?

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

Совершенно очевидно, что ES должен давать нам результаты, которые начинаются с нашего запроса.Как мы можем сказать ES предпочитать такие документы?

Добавление prefix поиск по keyword поле

Мы можем использовать prefix запрос, объединенный с matchзапрос с помощью запроса bool (который в данном случае можно приблизительно интерпретировать как OR), например:

POST my_phrase/doc/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "prefix": {
            "my_phrase.keyword": "i love dogs"
          }
        },
        {
          "match": {
            "my_phrase": "i love dogs"
          }
        }
      ]
    }
  }
}

Обратите внимание, что запрос prefix работает только с keyword type, так как он должен интерпретировать документ как один большой токен.

Этот запрос дает нам следующий порядок результатов: 2 - 5 - 1 - 3 - 4 - 6.

2вскочил, но 1 нет.Почему это произошло?

Здесь вводится регистр символов: keyword тип данных не анализируется, и, таким образом, i или I будут иметь значение для поиска префикса.

Как мы можем сделать keyword без учета регистра?

Создание keyword без учета регистра

Это достигается путем определения нормализатора в отображении:

PUT my_phrase2
{
  "settings": {
    "analysis": {
      "normalizer": {
        "my_normalizer": {
          "type": "custom",
          "char_filter": [],
          "filter": ["lowercase"]
        }
      }
    }
  },
  "mappings": {
    "doc": {
      "properties": {
        "my_phrase": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256,
                "normalizer": "my_normalizer"
              }
            }
          }
      }
    }
  }
}

Теперь тот же запрос даст нам следующий порядок: 1 - 2 - 5 - 3 - 4 - 6.

Это уже довольно хорошо, но 5 - I love horses and dogs все еще слишком высоко - выше, чем 3 - birds good but i love dogs and horsesс точным совпадением фразы.

match запрос не заботится о порядке слов в фразе.Можем ли мы повысить документы, которые имеют правильный порядок?

Добавление match_phrase для повышения соответствия фраз

Существует match_phrase запрос, который поддерживает токены в оригиналепорядок.Давайте использовать его в запросе:

POST my_phrase2/doc/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "prefix": {
            "my_phrase.keyword": "i love dogs"
          }
        },
        {
          "match_phrase": {
            "my_phrase": "i love dogs"
          }
        },
        {
          "match": {
            "my_phrase": "i love dogs"
          }
        }
      ]
    }
  }
}

Это дает нам следующий порядок: 1 - 2 - 3 - 5 - 4 - 6.

3 выскочил!Но 5 - I love horses and dogs все еще выше, чем 4 - Horses and i love dogs.Похоже, что совпадение фраз должно было бы быть 4.

Запрос стал довольно сложным, давайте выясним, какие его части действительно совпадают в документах.

Добавление имен к запросам

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

POST my_phrase2/doc/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "should": [
              {
                "prefix": {
                  "my_phrase.keyword": "i love dogs"
                }
              }
            ],
            "_name": "prefix"
          }
        },
...

Ответ на документы, представляющие интерес, даст нам:

  {
    "_score": 0.8630463,
    "_source": {
      "my_phrase": "I love horses and dogs",
      "expected_position": 5
    },
    "matched_queries": [
      "match"
    ]
  },
  {
    "_score": 0.82221067,
    "_source": {
      "my_phrase": "Horses and i love dogs",
      "expected_position": 4
    },
    "matched_queries": [
      "match",
      "phrase"
    ]
  },

Документ 5 не соответствует части phrase.Похоже, колебания счета снова нас ударили.

Фразовый запрос выглядит более актуально, есть ли способ повысить его?

Наконец: увеличение запросов на фразы и префиксы

Существует способ повлиять на вычислениеОценка, говорящая ES, что некоторые части запроса более важны, называется boost .Вот как это может выглядеть:

POST my_phrase2/doc/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "should": [
              {
                "prefix": {
                  "my_phrase.keyword": "i love dogs"
                }
              }
            ],
            "_name": "prefix",
            "boost": 2
          }
        },
        {
          "bool": {
            "should": [
              {
                "match": {
                  "my_phrase": "i love dogs"
                }
              }
            ],
            "_name": "match"
          }
        },
        {
          "bool": {
            "should": [
              {
                "match_phrase": {
                  "my_phrase": "i love dogs"
                }
              }
            ],
            "_name": "phrase",
            "boost": 2
          }
        }
      ]
    }
  }
}

Этот дает нам желаемый порядок результатов: 1 - 2 - 3 - 4 - 5 - 6.

Обратите внимание, что мы также увеличили запрос prefix, потому что мы хотелипонизьте важность match.

Безопасен ли этот подход или предупреждение о переобучении

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

Запрос, который идеально соответствует этим 6 документам, может не соответствовать большой реальной коллекции. Пожалуйста, примите этот ответ в качестве начала для оптимизации.

Как видите, не все части запросанеобходимо: имена запросов можно легко опустить, но они помогают понять, как сопоставляется документ.

Надеюсь, это поможет!

0 голосов
/ 02 июня 2018

Чтобы получить желаемые результаты, вам нужно использовать match_phrase_prefix с такими параметрами, как max_expansions пример ниже для дальнейшего чтения.

match_phrase_prefix

GET /_search
{
    "query": {
        "match_phrase_prefix" : {
            "message" : "quick brown f"
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...