More like this query

More Like This Queryは、指定された文書のセットに「似た」文書を見つけます。そのために、MLTはこれらの入力文書の代表的な用語のセットを選択し、これらの用語を使用してクエリを形成し、クエリを実行して結果を返します。ユーザーは入力文書、用語の選択方法、およびクエリの形成方法を制御します。

最も単純な使用ケースは、提供されたテキストに似た文書を要求することです。ここでは、「Once upon a time」というテキストが「タイトル」と「説明」フィールドに似ているすべての映画を要求しており、選択される用語の数を12に制限しています。

Python

  1. resp = client.search(
  2. query={
  3. "more_like_this": {
  4. "fields": [
  5. "title",
  6. "description"
  7. ],
  8. "like": "Once upon a time",
  9. "min_term_freq": 1,
  10. "max_query_terms": 12
  11. }
  12. },
  13. )
  14. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. more_like_this: {
  5. fields: [
  6. 'title',
  7. 'description'
  8. ],
  9. like: 'Once upon a time',
  10. min_term_freq: 1,
  11. max_query_terms: 12
  12. }
  13. }
  14. }
  15. )
  16. puts response

Js

  1. const response = await client.search({
  2. query: {
  3. more_like_this: {
  4. fields: ["title", "description"],
  5. like: "Once upon a time",
  6. min_term_freq: 1,
  7. max_query_terms: 12,
  8. },
  9. },
  10. });
  11. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "more_like_this" : {
  5. "fields" : ["title", "description"],
  6. "like" : "Once upon a time",
  7. "min_term_freq" : 1,
  8. "max_query_terms" : 12
  9. }
  10. }
  11. }

より複雑な使用ケースは、インデックスに既に存在する文書とテキストを混合することです。この場合、文書を指定するための構文は、Multi GET APIで使用されるものに似ています。

Python

  1. resp = client.search(
  2. query={
  3. "more_like_this": {
  4. "fields": [
  5. "title",
  6. "description"
  7. ],
  8. "like": [
  9. {
  10. "_index": "imdb",
  11. "_id": "1"
  12. },
  13. {
  14. "_index": "imdb",
  15. "_id": "2"
  16. },
  17. "and potentially some more text here as well"
  18. ],
  19. "min_term_freq": 1,
  20. "max_query_terms": 12
  21. }
  22. },
  23. )
  24. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. more_like_this: {
  5. fields: [
  6. 'title',
  7. 'description'
  8. ],
  9. like: [
  10. {
  11. _index: 'imdb',
  12. _id: '1'
  13. },
  14. {
  15. _index: 'imdb',
  16. _id: '2'
  17. },
  18. 'and potentially some more text here as well'
  19. ],
  20. min_term_freq: 1,
  21. max_query_terms: 12
  22. }
  23. }
  24. }
  25. )
  26. puts response

Js

  1. const response = await client.search({
  2. query: {
  3. more_like_this: {
  4. fields: ["title", "description"],
  5. like: [
  6. {
  7. _index: "imdb",
  8. _id: "1",
  9. },
  10. {
  11. _index: "imdb",
  12. _id: "2",
  13. },
  14. "and potentially some more text here as well",
  15. ],
  16. min_term_freq: 1,
  17. max_query_terms: 12,
  18. },
  19. },
  20. });
  21. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "more_like_this": {
  5. "fields": [ "title", "description" ],
  6. "like": [
  7. {
  8. "_index": "imdb",
  9. "_id": "1"
  10. },
  11. {
  12. "_index": "imdb",
  13. "_id": "2"
  14. },
  15. "and potentially some more text here as well"
  16. ],
  17. "min_term_freq": 1,
  18. "max_query_terms": 12
  19. }
  20. }
  21. }

最終的に、ユーザーはテキストを混合し、選択した文書のセットを提供することができますが、インデックスに必ずしも存在しない文書を提供することもできます。インデックスに存在しない文書を提供するための構文は、人工文書に似ています。

Python

  1. resp = client.search(
  2. query={
  3. "more_like_this": {
  4. "fields": [
  5. "name.first",
  6. "name.last"
  7. ],
  8. "like": [
  9. {
  10. "_index": "marvel",
  11. "doc": {
  12. "name": {
  13. "first": "Ben",
  14. "last": "Grimm"
  15. },
  16. "_doc": "You got no idea what I'd... what I'd give to be invisible."
  17. }
  18. },
  19. {
  20. "_index": "marvel",
  21. "_id": "2"
  22. }
  23. ],
  24. "min_term_freq": 1,
  25. "max_query_terms": 12
  26. }
  27. },
  28. )
  29. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. more_like_this: {
  5. fields: [
  6. 'name.first',
  7. 'name.last'
  8. ],
  9. like: [
  10. {
  11. _index: 'marvel',
  12. doc: {
  13. name: {
  14. first: 'Ben',
  15. last: 'Grimm'
  16. },
  17. _doc: "You got no idea what I'd... what I'd give to be invisible."
  18. }
  19. },
  20. {
  21. _index: 'marvel',
  22. _id: '2'
  23. }
  24. ],
  25. min_term_freq: 1,
  26. max_query_terms: 12
  27. }
  28. }
  29. }
  30. )
  31. puts response

Js

  1. const response = await client.search({
  2. query: {
  3. more_like_this: {
  4. fields: ["name.first", "name.last"],
  5. like: [
  6. {
  7. _index: "marvel",
  8. doc: {
  9. name: {
  10. first: "Ben",
  11. last: "Grimm",
  12. },
  13. _doc: "You got no idea what I'd... what I'd give to be invisible.",
  14. },
  15. },
  16. {
  17. _index: "marvel",
  18. _id: "2",
  19. },
  20. ],
  21. min_term_freq: 1,
  22. max_query_terms: 12,
  23. },
  24. },
  25. });
  26. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "more_like_this": {
  5. "fields": [ "name.first", "name.last" ],
  6. "like": [
  7. {
  8. "_index": "marvel",
  9. "doc": {
  10. "name": {
  11. "first": "Ben",
  12. "last": "Grimm"
  13. },
  14. "_doc": "You got no idea what I'd... what I'd give to be invisible."
  15. }
  16. },
  17. {
  18. "_index": "marvel",
  19. "_id": "2"
  20. }
  21. ],
  22. "min_term_freq": 1,
  23. "max_query_terms": 12
  24. }
  25. }
  26. }

How it Works

特定の入力文書に似たすべての文書を見つけたいと仮定します。明らかに、入力文書自体はそのタイプのクエリに対して最良の一致であるべきです。その理由は、主にLuceneスコアリング公式によるもので、最も高いtf-idfを持つ用語によるものです。したがって、入力文書の中で最も高いtf-idfを持つ用語は、その文書の良い代表者であり、類似の文書を取得するために排他的クエリ(またはOR)内で使用できます。MLTクエリは、単に入力文書からテキストを抽出し、それを分析し、通常はフィールドで同じアナライザーを使用して、最も高いtf-idfを持つ上位K用語を選択して、これらの用語の排他的クエリを形成します。

MLTを実行するフィールドは、インデックスされており、textまたはkeywordのタイプである必要があります。さらに、likeを文書と共に使用する場合、_sourceが有効であるか、フィールドがstoredであるか、term_vectorを保存する必要があります。分析を高速化するために、インデックス時に用語ベクトルを保存することが役立つ場合があります。

たとえば、「タイトル」と「tags.raw」フィールドでMLTを実行したい場合、インデックス時にそれらのterm_vectorを明示的に保存できます。「説明」と「tags」フィールドでMLTを実行することもできますが、_sourceはデフォルトで有効になっているため、これらのフィールドの分析の速度は向上しません。

Python

  1. resp = client.indices.create(
  2. index="imdb",
  3. mappings={
  4. "properties": {
  5. "title": {
  6. "type": "text",
  7. "term_vector": "yes"
  8. },
  9. "description": {
  10. "type": "text"
  11. },
  12. "tags": {
  13. "type": "text",
  14. "fields": {
  15. "raw": {
  16. "type": "text",
  17. "analyzer": "keyword",
  18. "term_vector": "yes"
  19. }
  20. }
  21. }
  22. }
  23. },
  24. )
  25. print(resp)

Ruby

  1. response = client.indices.create(
  2. index: 'imdb',
  3. body: {
  4. mappings: {
  5. properties: {
  6. title: {
  7. type: 'text',
  8. term_vector: 'yes'
  9. },
  10. description: {
  11. type: 'text'
  12. },
  13. tags: {
  14. type: 'text',
  15. fields: {
  16. raw: {
  17. type: 'text',
  18. analyzer: 'keyword',
  19. term_vector: 'yes'
  20. }
  21. }
  22. }
  23. }
  24. }
  25. }
  26. )
  27. puts response

Js

  1. const response = await client.indices.create({
  2. index: "imdb",
  3. mappings: {
  4. properties: {
  5. title: {
  6. type: "text",
  7. term_vector: "yes",
  8. },
  9. description: {
  10. type: "text",
  11. },
  12. tags: {
  13. type: "text",
  14. fields: {
  15. raw: {
  16. type: "text",
  17. analyzer: "keyword",
  18. term_vector: "yes",
  19. },
  20. },
  21. },
  22. },
  23. },
  24. });
  25. console.log(response);

Console

  1. PUT /imdb
  2. {
  3. "mappings": {
  4. "properties": {
  5. "title": {
  6. "type": "text",
  7. "term_vector": "yes"
  8. },
  9. "description": {
  10. "type": "text"
  11. },
  12. "tags": {
  13. "type": "text",
  14. "fields": {
  15. "raw": {
  16. "type": "text",
  17. "analyzer": "keyword",
  18. "term_vector": "yes"
  19. }
  20. }
  21. }
  22. }
  23. }
  24. }

Parameters

唯一の必須パラメータはlikeであり、他のすべてのパラメータには妥当なデフォルトがあります。パラメータには3つのタイプがあります:1つは文書入力を指定するため、もう1つは用語選択とクエリ形成のためです。

Document Input Parameters

like MLTクエリの唯一の必須パラメータはlikeであり、柔軟な構文に従います。この構文では、ユーザーは自由形式のテキストおよび/または単一または複数の文書を指定できます(上記の例を参照)。文書を指定するための構文は、Multi GET APIで使用されるものに似ています。文書を指定する際、テキストはfieldsから取得されますが、各文書リクエストでオーバーライドされる場合があります。テキストはフィールドのアナライザーによって分析されますが、オーバーライドされることもあります。フィールドのアナライザーをオーバーライドするための構文は、Term Vectors APIper_field_analyzerパラメータの構文に似ています。さらに、インデックスに必ずしも存在しない文書を提供するために、人工文書もサポートされています。
unlike unlikeパラメータは、likeと組み合わせて使用され、選択した文書のセットに見つかった用語を選択しないようにします。言い換えれば、like: "Apple"の文書を要求することができますが、unlike: "cake crumble tree"。構文はlikeと同じです。

| fields | テキストを取得して分析するフィールドのリスト。デフォルトはindex.query.default_fieldインデックス設定で、デフォルト値は*です。*値は、メタデータフィールドを除く用語レベル\
クエリ
に適格なすべてのフィールドに一致します。

Term Selection Parameters

max_query_terms 選択されるクエリ用語の最大数。この値を増やすと、クエリ実行速度の代償として精度が向上します。デフォルトは25です。
min_term_freq 用語が入力文書から無視される最小用語頻度。デフォルトは2です。
min_doc_freq 用語が入力文書から無視される最小文書頻度。デフォルトは5です。
max_doc_freq 用語が入力文書から無視される最大文書頻度。これは、ストップワードのような非常に頻繁に使用される単語を無視するために役立つ場合があります。デフォルトは無制限(Integer.MAX_VALUE、すなわち2^31-1または2147483647)です。
min_word_length 用語が無視される最小単語長。デフォルトは0です。
max_word_length 用語が無視される最大単語長。デフォルトは無制限(0)です。
stop_words ストップワードの配列。このセット内の任意の単語は「興味がない」と見なされ、無視されます。アナライザーがストップワードを許可する場合、MLTにそれらを明示的に無視するように指示することが望ましいかもしれません。文書の類似性の目的では、「ストップワードは決して興味がない」と仮定するのが合理的です。

| analyzer | 自由形式のテキストを分析するために使用されるアナライザー。デフォルトはfieldsの最初のフィールドに関連付けられたアナライザーです。

Query Formation Parameters

minimum_should_match 排他的クエリが形成された後、このパラメータは一致する必要がある用語の数を制御します。
この構文は、minimum should matchと同じです。
(デフォルトは"30%"です)。
fail_on_unsupported_field 指定されたフィールドのいずれかがサポートされているタイプ(textまたはkeyword)でない場合、クエリが失敗するか(例外をスローする)を制御します。
これをfalseに設定すると、フィールドを無視して処理を続行します。デフォルトはtrueです。
boost_terms 形成されたクエリの各用語は、tf-idfスコアによってさらにブーストされる可能性があります。
この機能を使用する際のブースト係数を設定します。デフォルトは無効(0)です。他の正の値は、指定されたブースト係数で用語のブーストを有効にします。
include 入力文書も検索結果に含めるべきかどうかを指定します。
デフォルトはfalseです。

| boost | クエリ全体のブースト値を設定します。デフォルトは1.0です。

Alternative

類似文書のクエリ構築をより制御するために、選択した用語を例文書からブールクエリに組み立てるカスタムクライアントコードを書くことを検討する価値があります。テキストの一部から「興味のある」単語を選択するmore_like_thisのロジックは、TermVectors APIを介してもアクセス可能です。たとえば、termvectors APIを使用すると、文書のテキストに見つかったトピックキーワードの選択をユーザーに提示し、興味のある単語を選択して掘り下げることができるようになります。more_like_thisによって使用されるマッチングのより「ブラックボックス」アプローチを使用するのではなく。