35

ブック検索にESを使いたいです。そこで、次のように著者名とタイトルを (ネストされたドキュメントとして) インデックスに入れることにしました。

curl -XPUT localhost:9200/library/search_books/1 -d'{
  "author": "one",
  "books": [
    {
      "title": "two",
    },
    {
      "title": "three",
    }
  ]
}'

私が得られないのは、検索クエリをどのように構成して、「one two」を検索するときに book 2 のみを検索し、「two three」を検索するときに何も検索せず、「one」を検索するときにすべての本を検索する必要があるかということです。

4

2 に答える 2

35

おそらくこのようなものですか?

{
  "query":{
    "bool":{
      "must":[
        {
          "term":{
            "author":"one"
          }
        },
        {
          "nested":{
            "path":"books",
            "query":{
              "term":{
                "books.title":"two"
              }
            }
          }
        }
      ]
    }
  }
}

そのクエリは基本的に、ドキュメントにはとが必要であると言っていauthor: oneますbooks.title: two。そのクエリは簡単に再構成できます。たとえば、著者を検索するだけの場合は、ネストされた部分を削除します。別の本が必要な場合は、ネストなどを変更してください。

これは、内部オブジェクトではなく、実際のネストされたドキュメントを使用していることを前提としています。内部オブジェクトの場合、特別なネストされたクエリを使用せずに、完全修飾パスを使用できます。

Edit1:これは、おおよその解決策にすぎませんが、インデックス時に巧妙にブーストすることでおそらく達成できます。「作成者」が大幅にブーストされると、タイトルがクエリの両方の部分に一致する場合でも、タイトルだけに一致するよりも上位に並べ替えられます。次に、min_scoreカットオフを使用して、それらが表示されないようにすることができます。

一部が忍び寄る可能性があるため、これは大まかな概算にすぎません。また、「正しい」一致間の一般的な並べ替えに奇妙なことをする可能性があります。

Edit2: 「単一入力」オプションを公開するためにquery_stringを使用して更新:


{
  "query":{
    "query_string" : {
      "query" : "+author:one +books.title:two"
    }
  }
}

これは、デフォルトの「内部オブジェクト」を使用していることを前提としています。実際のネストされた型がある場合、query_stringははるかに複雑になります。


{
  "query":{
    "query_string" : {
      "query" : "+author:one +BlockJoinQuery (filtered(books.title:two)->cache(_type:__books))"
    }
  }
}

巨大な免責事項私はこれらの2つのquery_stringsのどちらもテストしなかったので、正確に正しくない可能性があります。しかし、彼らはLucene構文が過度に友好的ではないことを示しています。


Edit3-これは私の最高のアイデアです:

それについて考えた後、あなたの最善の解決策は、著者と本のタイトルを連結する特別なフィールドに索引を付けることかもしれません。このようなもの:

{
  "author": "one",
  "books": [
    {
      "title": "two",
    },
    {
      "title": "three",
    }
  ],
  "author_book": [ "one two", "one three" ]
}

次に、検索時に、次の用語と完全に一致させることができますauthor_book

{
  "query" : {
    "term" : {
      "author_book" : "one two"
    }
  }
}
于 2013-03-22T23:47:04.037 に答える
4

この投稿で答えを見つけました: Elasticsearch の子供とネストされたドキュメントを楽しむ。ネストされた Document が鍵です。マッピング:

{
  "book":{
    "properties": {
      "tags": { "type": "multi_field",
        "fields": {
            "tags": { "type": "string", "store":"yes", "index": "analyzed" },
            "facet": { "type": "string", "store":"yes", "index": "not_analyzed" }
        }
      },
      "editions": { "type": "nested", 
        "properties": {
          "title_author": { "type": "string", "store": "yes", "index": "analyzed" },
          "title": { "type": "string", "store": "yes", "index": "analyzed" }
        }
      }
    }
  }
}

ドキュメント:

"tags": ["novel", "crime"],
  "editions": [
    {
      "title": "two",
      "title_author": "two one"
    },
    {
      "title": "three",
      "title_author": "three one"
    }
  ]

今、私は次のように検索できます:

{

  "query": {
    "bool": {
      "should": [
        {
          "nested": {
            "path": "editions",
            "query": {
              "match": {
                "editions.title_author": {
                  "query": "one two",
                  "operator": "and"
                }
              }
            }
          }
        }
      ]
    }
  }
}

また、「ツー スリー」で検索しても一致しません。「ワン ツー」または「ワン スリー」で 1 を取得します。バージョン 1.1.0 では、multi_match クエリとオプション cross_fields を使用した別のオプションがあり、タイトルを繰り返さず、ネストされた各ドキュメントに著者名のみを追加できます。これにより、インデックスが小さくなります。

于 2014-03-07T14:51:16.763 に答える