Вопрос: Elasticsearch «Больше похоже на этот» API против более_подобного запроса


Elasticsearch имеет две аналогичные функции для получения «похожих» документов:

Здесь «Больше похоже на этот API» , Это дает мне документы, похожие на данные. Однако я не могу использовать его в более сложных выражениях.

Существует также "more_like_this" запрос для использования в API поиска  Я могу использовать его в bool или boosting выражениях, но я не могу дать ему идентификатор документа. Я должен предоставить "like_text" параметр.

У меня есть документы с тегами и контентом. В некоторых документах будут хорошие теги, а у некоторых их не будет. Мне нужна функция «Подобные документы», которая будет работать каждый раз, но ранжирует документы с соответствующими тегами выше, чем документы с соответствующим текстом. Моя идея:

{
    "boosting" : {
        "positive" : {
            "more_like_this" : {
                "fields" : ["tag"],
                "id" : "23452",
                "min_term_freq" : 1
            }
        },
        "negative" : {
            "more_like_this" : {
                "fields" : ["tag"],
                "id" : "23452",
            }
        },
        "negative_boost" : 0.2
    }
}

Очевидно, это не работает, потому что нет "id" в "more_like_this", Каковы альтернативы?


20


источник


Ответы:


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

Чтобы достичь этого, нам нужно извлечь какой-либо контент из текущего документа и использовать его, чтобы сделать запрос, чтобы получить аналогичные. Мы можем извлекать содержимое из сохраненных полей lucene (или поля elasksearch _source, которое фактически является сохраненным полем в lucene) и каким-то образом анализировать его или использовать информацию, хранящуюся в векторах термина (если включена при индексировании), чтобы получить список терминов которые мы можем использовать для запроса, без необходимости повторного анализа текста. Я не уверен, пытается ли elasticsearch этот последний подход, если доступны векторы векторов.

больше похоже на этот запрос  позволяет вам предоставить текст, независимо от того, откуда вы его взяли. Этот текст будет использоваться для запроса выбранных полей и возврата похожих документов. Текст не будет полностью использоваться, но повторно проанализирован, и только максимум max_query_terms (по умолчанию 25) будет сохранено, из условий, которые имеют как минимум предоставленные min_term_freq (минимальная временная частота, значение по умолчанию 2) и частота документа между min_doc_freq а также max_doc_freq, Также есть несколько параметров, которые могут влиять на сгенерированный запрос.

больше похоже на api  идет еще на один шаг, позволяя предоставить идентификатор документа и, опять же, список полей. Содержимое этих полей будет извлечено из этого конкретного документа и использовано для того, чтобы сделать этот запрос похожим на те же поля. Это означает, что сгенерированный больше похожий на этот запрос будет содержать текст свойства, содержащий ранее извлеченный текст, и будет выполняться в тех же самых полях. Как вы можете видеть, больше похоже на то, что api выполняет подобный запрос под капотом.

Предположим, что подобный запрос дает вам больше гибкости, поскольку вы можете комбинировать его с другими запросами, и вы можете получить текст из любого источника, который вам нравится. С другой стороны, более похожее на это api предоставляет общую функциональность, делая для вас еще большую работу, но с некоторыми ограничениями.

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

Существуют разные способы достижения желаемого. Я бы использовал bool query  объединить два других, подобных этим запросам, в клаузуле и дать им другой вес. Я также использовал бы больше похоже на этот запрос поля  вместо этого, поскольку вы хотите запросить одно поле за раз.

{
    "bool" : {
        "must" : {
          {"match_all" : { }}
        },
        "should" : [
            {
              "more_like_this_field" : {
                "tags" : {
                  "like_text" : "here go the tags extracted from the current document!",
                  "boost" : 2.0
                }
              }
            },
            {
              "more_like_this_field" : {
                "content" : {
                  "like_text" : "here goes the content extracted from the current document!"
                }
              }
            }
        ],
        "minimum_number_should_match" : 1
    }
}

Таким образом, по крайней мере одно из предложений должно соответствовать, а совпадение с тегами более важно, чем совпадение содержимого.


41



Это возможно теперь с новым как  синтаксис:

{
    "more_like_this" : {
        "fields" : ["title", "description"],
        "like" : [
        {
            "_index" : "imdb",
            "_type" : "movies",
            "_id" : "1"
        },
        {
            "_index" : "imdb",
            "_type" : "movies",
            "_id" : "2"
        }],
        "min_term_freq" : 1,
        "max_query_terms" : 12
    }
}

Глянь сюда: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-mlt-query.html


9