6

Java アプリケーションで ElasticSearch を使用する際に問題が発生しています。私は自分自身を説明します、私は次のようなマッピングを持っています:

{
"products": {
    "properties": {
        "id": {
            "type": "long",
                   "ignore_malformed": false
        },
        "locations": {
            "properties": {
                "category": {
                    "type": "long",
                   "ignore_malformed": false
                },
                "subCategory": {
                    "type": "long",
                   "ignore_malformed": false
                },
                "order": {
                    "type": "long",
                   "ignore_malformed": false
                }
            }
        },
...

ご覧のとおり、場所で構成される製品のリストを受け取ります。私のモデルでは、この場所はすべてのカテゴリの製品です。これは、製品が 1 つ以上のカテゴリに属する​​ことができることを意味します。このカテゴリのそれぞれで、製品には注文があります。これは、クライアントが表示したい注文です。

たとえば、ダイヤモンド製品は、ジュエリーでは 1 位ですが、女性では 3 位になることがあります (私の例はあまり論理的ではありません ^^)。そこで、[ジュエリー] をクリックすると、この特定のカテゴリの locations.order フィールドで並べられたこの商品を表示したいと思います。

今のところ、特定のカテゴリのすべての製品を検索すると、受信した ElasticSearch の応答は次のようになります。

{"id":5331880,"locations":[{"category":5322606,"order":1},
{"category":5883712,"subCategory":null,"order":3},
{"category":5322605,"subCategory":6032961,"order":2},.......

この商品を、検索している特定のカテゴリの location.order 要素で並べ替えることはできますか? たとえば、カテゴリ 5322606 を照会している場合、この製品の注文 1 を取得する必要があります。

よろしくお願いします!よろしく、オリヴィエ。

4

2 に答える 2

9

最初に用語の修正: Elasticsearch では、「親/子」は完全に別個のドキュメントを指し、子ドキュメントは親ドキュメントを指します。親と子は同じシャードに格納されますが、個別に更新できます。

nested上記の例では、達成しようとしていることはドキュメントで実行できます。

現在、あなたのlocationsフィールドは ですtype:"object"。これは、各場所の値が次のように平坦化されることを意味します。

{ 
    "locations.category": [5322606, 5883712, 5322605],
    "locations.subCategory": [6032961],
    "locations.order": [1, 3, 2]
}

category: 5322606つまり、「サブ」フィールドは複数値フィールドにフラット化されます。これは、 と の間に相関関係がないため、役に立ちませんorder: 1

ただし、に変更locationsするとtype:"nested"、内部的に各場所が個別のドキュメントとしてインデックス化されます。つまり、専用のnested クエリフィルターを使用して、各場所を個別にクエリできます。

デフォルトでは、nestedクエリは_score各場所の一致度に基づいて を返しますが、この場合、order一致する子からフィールドの最高値を返したいと考えています。これを行うには、custom_scoreクエリを使用する必要があります。

それでは、適切なマッピングを使用してインデックスを作成することから始めましょう。

curl -XPUT 'http://127.0.0.1:9200/test/?pretty=1'  -d '
{
   "mappings" : {
      "products" : {
         "properties" : {
            "locations" : {
               "type" : "nested",
               "properties" : {
                  "order" : {
                     "type" : "long"
                  },
                  "subCategory" : {
                     "type" : "long"
                  },
                  "category" : {
                     "type" : "long"
                  }
               }
            },
            "id" : {
               "type" : "long"
            }
         }
      }
   }
}
'

サンプル ドキュメントのインデックスを作成します。

curl -XPOST 'http://127.0.0.1:9200/test/products?pretty=1'  -d '
{
   "locations" : [
      {
         "order" : 1,
         "category" : 5322606
      },
      {
         "order" : 3,
         "subCategory" : null,
         "category" : 5883712
      },
      {
         "order" : 2,
         "subCategory" : 6032961,
         "category" : 5322605
      }
   ],
   "id" : 5331880
}
'

これで、上で説明したクエリを使用して検索できます。

curl -XGET 'http://127.0.0.1:9200/test/products/_search?pretty=1'  -d '
{
   "query" : {
      "nested" : {
         "query" : {
            "custom_score" : {
               "script" : "doc[\u0027locations.order\u0027].value",
               "query" : {
                  "constant_score" : {
                     "filter" : {
                        "and" : [
                           {
                              "term" : {
                                 "category" : 5322605
                              }
                           },
                           {
                              "term" : {
                                 "subCategory" : 6032961
                              }
                           }
                        ]
                     }
                  }
               }
            }
         },
         "score_mode" : "max",
         "path" : "locations"
      }
   }
}
'

注: スクリプト内の単一引用符は、\u0027シェルの引用を回避するためにエスケープされています。スクリプトは実際には次のようになります。"doc['locations.order'].value"

結果からを見ると、一致する_scoreの値が使用されていることがわかります。orderlocation

{
   "hits" : {
      "hits" : [
         {
            "_source" : {
               "locations" : [
                  {
                     "order" : 1,
                     "category" : 5322606
                  },
                  {
                     "order" : 3,
                     "subCategory" : null,
                     "category" : 5883712
                  },
                  {
                     "order" : 2,
                     "subCategory" : 6032961,
                     "category" : 5322605
                  }
               ],
               "id" : 5331880
            },
            "_score" : 2,
            "_index" : "test",
            "_id" : "cXTFUHlGTKi0hKAgUJFcBw",
            "_type" : "products"
         }
      ],
      "max_score" : 2,
      "total" : 1
   },
   "timed_out" : false,
   "_shards" : {
      "failed" : 0,
      "successful" : 5,
      "total" : 5
   },
   "took" : 9
}
于 2013-01-25T10:31:45.590 に答える
0

親を子フィールドでソートすることに関連する、より更新されたバージョンを追加するだけです。次のように、子フィールド (「カウント」など) でソートされた親ドキュメント タイプをクエリできます。

https://gist.github.com/robinloxley1/7ea7c4f37a3413b1ca16

于 2016-02-29T03:37:27.837 に答える