2013-08-28 19:24:34 -04:00
|
|
|
[[query-dsl-mlt-query]]
|
2015-06-03 19:59:22 -04:00
|
|
|
=== More Like This Query
|
2013-08-28 19:24:34 -04:00
|
|
|
|
2016-11-29 13:07:01 -05:00
|
|
|
The More Like This Query finds documents that are "like" a given
|
2015-01-19 09:08:09 -05:00
|
|
|
set of documents. In order to do so, MLT selects a set of representative terms
|
|
|
|
of these input documents, forms a query using these terms, executes the query
|
|
|
|
and returns the results. The user controls the input documents, how the terms
|
2016-11-29 13:07:01 -05:00
|
|
|
should be selected and how the query is formed.
|
2015-01-19 09:08:09 -05:00
|
|
|
|
|
|
|
The simplest use case consists of asking for documents that are similar to a
|
|
|
|
provided piece of text. Here, we are asking for all movies that have some text
|
|
|
|
similar to "Once upon a time" in their "title" and in their "description"
|
|
|
|
fields, limiting the number of selected terms to 12.
|
2013-08-28 19:24:34 -04:00
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
GET /_search
|
2013-08-28 19:24:34 -04:00
|
|
|
{
|
2016-05-24 05:58:43 -04:00
|
|
|
"query": {
|
|
|
|
"more_like_this" : {
|
|
|
|
"fields" : ["title", "description"],
|
|
|
|
"like" : "Once upon a time",
|
|
|
|
"min_term_freq" : 1,
|
|
|
|
"max_query_terms" : 12
|
|
|
|
}
|
2013-08-28 19:24:34 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
// CONSOLE
|
2013-08-28 19:24:34 -04:00
|
|
|
|
2015-01-19 09:08:09 -05:00
|
|
|
A more complicated use case consists of mixing texts with documents already
|
|
|
|
existing in the index. In this case, the syntax to specify a document is
|
|
|
|
similar to the one used in the <<docs-multi-get,Multi GET API>>.
|
2014-04-17 11:09:20 -04:00
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
GET /_search
|
2014-04-17 11:09:20 -04:00
|
|
|
{
|
2016-05-24 05:58:43 -04:00
|
|
|
"query": {
|
|
|
|
"more_like_this" : {
|
|
|
|
"fields" : ["title", "description"],
|
|
|
|
"like" : [
|
|
|
|
{
|
|
|
|
"_index" : "imdb",
|
|
|
|
"_type" : "movies",
|
|
|
|
"_id" : "1"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"_index" : "imdb",
|
|
|
|
"_type" : "movies",
|
|
|
|
"_id" : "2"
|
|
|
|
},
|
|
|
|
"and potentially some more text here as well"
|
|
|
|
],
|
|
|
|
"min_term_freq" : 1,
|
|
|
|
"max_query_terms" : 12
|
|
|
|
}
|
2014-04-17 11:09:20 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
// CONSOLE
|
2014-04-17 11:09:20 -04:00
|
|
|
|
2015-01-19 09:08:09 -05:00
|
|
|
Finally, users can mix some texts, a chosen set of documents but also provide
|
|
|
|
documents not necessarily present in the index. To provide documents not
|
|
|
|
present in the index, the syntax is similar to <<docs-termvectors-artificial-doc,artificial documents>>.
|
2014-09-15 10:17:49 -04:00
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
GET /_search
|
2014-09-15 10:17:49 -04:00
|
|
|
{
|
2016-05-24 05:58:43 -04:00
|
|
|
"query": {
|
|
|
|
"more_like_this" : {
|
|
|
|
"fields" : ["name.first", "name.last"],
|
|
|
|
"like" : [
|
|
|
|
{
|
|
|
|
"_index" : "marvel",
|
|
|
|
"_type" : "quotes",
|
|
|
|
"doc" : {
|
|
|
|
"name": {
|
|
|
|
"first": "Ben",
|
|
|
|
"last": "Grimm"
|
|
|
|
},
|
|
|
|
"tweet": "You got no idea what I'd... what I'd give to be invisible."
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"_index" : "marvel",
|
|
|
|
"_type" : "quotes",
|
|
|
|
"_id" : "2"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"min_term_freq" : 1,
|
|
|
|
"max_query_terms" : 12
|
2014-09-15 10:17:49 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
// CONSOLE
|
2014-09-15 10:17:49 -04:00
|
|
|
|
2015-06-03 19:59:22 -04:00
|
|
|
==== How it Works
|
2015-01-19 09:08:09 -05:00
|
|
|
|
|
|
|
Suppose we wanted to find all documents similar to a given input document.
|
|
|
|
Obviously, the input document itself should be its best match for that type of
|
|
|
|
query. And the reason would be mostly, according to
|
|
|
|
link:https://lucene.apache.org/core/4_9_0/core/org/apache/lucene/search/similarities/TFIDFSimilarity.html[Lucene scoring formula],
|
|
|
|
due to the terms with the highest tf-idf. Therefore, the terms of the input
|
|
|
|
document that have the highest tf-idf are good representatives of that
|
|
|
|
document, and could be used within a disjunctive query (or `OR`) to retrieve similar
|
|
|
|
documents. The MLT query simply extracts the text from the input document,
|
|
|
|
analyzes it, usually using the same analyzer at the field, then selects the
|
|
|
|
top K terms with highest tf-idf to form a disjunctive query of these terms.
|
|
|
|
|
|
|
|
IMPORTANT: The fields on which to perform MLT must be indexed and of type
|
2017-09-25 05:10:13 -04:00
|
|
|
`text` or `keyword``. Additionally, when using `like` with documents, either
|
|
|
|
`_source` must be enabled or the fields must be `stored` or store
|
|
|
|
`term_vector`. In order to speed up analysis, it could help to store term
|
|
|
|
vectors at index time.
|
2015-01-19 09:08:09 -05:00
|
|
|
|
|
|
|
For example, if we wish to perform MLT on the "title" and "tags.raw" fields,
|
|
|
|
we can explicitly store their `term_vector` at index time. We can still
|
|
|
|
perform MLT on the "description" and "tags" fields, as `_source` is enabled by
|
|
|
|
default, but there will be no speed up on analysis for these fields.
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
PUT /imdb
|
|
|
|
{
|
|
|
|
"mappings": {
|
|
|
|
"movies": {
|
|
|
|
"properties": {
|
|
|
|
"title": {
|
|
|
|
"type": "text",
|
|
|
|
"term_vector": "yes"
|
|
|
|
},
|
|
|
|
"description": {
|
|
|
|
"type": "text"
|
|
|
|
},
|
|
|
|
"tags": {
|
|
|
|
"type": "text",
|
|
|
|
"fields" : {
|
|
|
|
"raw": {
|
|
|
|
"type" : "text",
|
|
|
|
"analyzer": "keyword",
|
|
|
|
"term_vector" : "yes"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-01-19 09:08:09 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
--------------------------------------------------
|
2016-05-24 05:58:43 -04:00
|
|
|
// CONSOLE
|
2013-08-28 19:24:34 -04:00
|
|
|
|
2015-06-03 19:59:22 -04:00
|
|
|
==== Parameters
|
2015-01-19 09:08:09 -05:00
|
|
|
|
|
|
|
The only required parameter is `like`, all other parameters have sensible
|
|
|
|
defaults. There are three types of parameters: one to specify the document
|
|
|
|
input, the other one for term selection and for query formation.
|
|
|
|
|
|
|
|
[float]
|
2015-06-03 19:59:22 -04:00
|
|
|
==== Document Input Parameters
|
2015-01-19 09:08:09 -05:00
|
|
|
|
|
|
|
[horizontal]
|
2015-10-07 07:27:36 -04:00
|
|
|
`like`::
|
2015-01-19 09:08:09 -05:00
|
|
|
The only *required* parameter of the MLT query is `like` and follows a
|
|
|
|
versatile syntax, in which the user can specify free form text and/or a single
|
|
|
|
or multiple documents (see examples above). The syntax to specify documents is
|
|
|
|
similar to the one used by the <<docs-multi-get,Multi GET API>>. When
|
|
|
|
specifying documents, the text is fetched from `fields` unless overridden in
|
|
|
|
each document request. The text is analyzed by the analyzer at the field, but
|
|
|
|
could also be overridden. The syntax to override the analyzer at the field
|
|
|
|
follows a similar syntax to the `per_field_analyzer` parameter of the
|
|
|
|
<<docs-termvectors-per-field-analyzer,Term Vectors API>>.
|
|
|
|
Additionally, to provide documents not necessarily present in the index,
|
|
|
|
<<docs-termvectors-artificial-doc,artificial documents>> are also supported.
|
|
|
|
|
2016-08-02 17:35:31 -04:00
|
|
|
`unlike`::
|
2015-05-12 08:31:26 -04:00
|
|
|
The `unlike` parameter is used in conjunction with `like` in order not to
|
|
|
|
select terms found in a chosen set of documents. In other words, we could ask
|
|
|
|
for documents `like: "Apple"`, but `unlike: "cake crumble tree"`. The syntax
|
|
|
|
is the same as `like`.
|
|
|
|
|
2015-01-19 09:08:09 -05:00
|
|
|
`fields`::
|
2017-08-28 11:43:59 -04:00
|
|
|
A list of fields to fetch and analyze the text from.
|
2015-01-19 09:08:09 -05:00
|
|
|
|
2015-10-07 07:27:36 -04:00
|
|
|
`like_text`::
|
2015-01-19 09:08:09 -05:00
|
|
|
The text to find documents like it.
|
|
|
|
|
2015-10-07 07:27:36 -04:00
|
|
|
`ids` or `docs`::
|
2015-01-19 09:08:09 -05:00
|
|
|
A list of documents following the same syntax as the <<docs-multi-get,Multi GET API>>.
|
|
|
|
|
|
|
|
[float]
|
2015-01-30 08:27:08 -05:00
|
|
|
[[mlt-query-term-selection]]
|
2015-06-03 19:59:22 -04:00
|
|
|
==== Term Selection Parameters
|
2015-01-19 09:08:09 -05:00
|
|
|
|
|
|
|
[horizontal]
|
|
|
|
`max_query_terms`::
|
|
|
|
The maximum number of query terms that will be selected. Increasing this value
|
|
|
|
gives greater accuracy at the expense of query execution speed. Defaults to
|
|
|
|
`25`.
|
|
|
|
|
|
|
|
`min_term_freq`::
|
|
|
|
The minimum term frequency below which the terms will be ignored from the
|
|
|
|
input document. Defaults to `2`.
|
|
|
|
|
|
|
|
`min_doc_freq`::
|
|
|
|
The minimum document frequency below which the terms will be ignored from the
|
|
|
|
input document. Defaults to `5`.
|
|
|
|
|
|
|
|
`max_doc_freq`::
|
|
|
|
The maximum document frequency above which the terms will be ignored from the
|
|
|
|
input document. This could be useful in order to ignore highly frequent words
|
|
|
|
such as stop words. Defaults to unbounded (`0`).
|
|
|
|
|
|
|
|
`min_word_length`::
|
|
|
|
The minimum word length below which the terms will be ignored. The old name
|
|
|
|
`min_word_len` is deprecated. Defaults to `0`.
|
|
|
|
|
|
|
|
`max_word_length`::
|
|
|
|
The maximum word length above which the terms will be ignored. The old name
|
|
|
|
`max_word_len` is deprecated. Defaults to unbounded (`0`).
|
|
|
|
|
|
|
|
`stop_words`::
|
|
|
|
An array of stop words. Any word in this set is considered "uninteresting" and
|
|
|
|
ignored. If the analyzer allows for stop words, you might want to tell MLT to
|
|
|
|
explicitly ignore them, as for the purposes of document similarity it seems
|
|
|
|
reasonable to assume that "a stop word is never interesting".
|
|
|
|
|
|
|
|
`analyzer`::
|
|
|
|
The analyzer that is used to analyze the free form text. Defaults to the
|
|
|
|
analyzer associated with the first field in `fields`.
|
|
|
|
|
|
|
|
[float]
|
2015-06-03 19:59:22 -04:00
|
|
|
==== Query Formation Parameters
|
2015-01-19 09:08:09 -05:00
|
|
|
|
|
|
|
[horizontal]
|
|
|
|
`minimum_should_match`::
|
|
|
|
After the disjunctive query has been formed, this parameter controls the
|
|
|
|
number of terms that must match.
|
|
|
|
The syntax is the same as the <<query-dsl-minimum-should-match,minimum should match>>.
|
|
|
|
(Defaults to `"30%"`).
|
|
|
|
|
|
|
|
`boost_terms`::
|
|
|
|
Each term in the formed query could be further boosted by their tf-idf score.
|
|
|
|
This sets the boost factor to use when using this feature. Defaults to
|
|
|
|
deactivated (`0`). Any other positive value activates terms boosting with the
|
|
|
|
given boost factor.
|
|
|
|
|
|
|
|
`include`::
|
|
|
|
Specifies whether the input documents should also be included in the search
|
|
|
|
results returned. Defaults to `false`.
|
|
|
|
|
|
|
|
`boost`::
|
|
|
|
Sets the boost value of the whole query. Defaults to `1.0`.
|