Space Vatican

データのインデックスを作成するとき、世界は孤立している各ドキュメントほど単純ではあ 場合によっては、すべてのデータを子ドキュメントに非正規化する方が良い場合があります。 たとえば、書籍をモデル化している場合、書籍にauthorフィールドを追加することは賢明な選択です(権威あるデータソースであるデータベースでデータが別々のauthorsbooks それは簡単で、本の属性と著者の名前の両方でクエリを簡単に構築できます。

それは必ずしも実用的ではありません-各子ドキュメントでそれを複製するには、親ドキュメントに多すぎるデータがある可能性があります。 あなたの典型的なブログ/コメントアプリを持っていた場合、あなたはこれが大幅にいくつかのインデックス付きデータの量を増加させるように、各コ しかし、それがなければ、特定の条件に一致する投稿のコメントを見つけるためのクエリを簡単に書くことはできません(最初に一致する投稿を見つ

別のオプションは、親文書の中に子文書を配置することです。

123456789101112
{ "name": "A. N Author", "biography": "A leading wordsmith", "books": }

ここでの欠点の1つは、子を追加するにはドキュメント全体のインデックスを再作成する必要があることです。 あるジャンルの本を書いた著者を見つけることは容易であるが、ペンギンによって出版されるsfの本があった著者を見つけることはより堅い。

インデックスに

が含まれている場合、最も明白なクエリ

は両方の著者を検索します-publishedgenreの条件が同じ本と一致する必要があることを表現

ElasticSearchはこれに役立つ2つのことを提供します。 最初は、ネストされたドキュメント/クエリの概念です。 これは、少なくとも一つの本があなたの基準の両方を満たす著者を探していると言うことができます。

まず、booksフィールドがネストされることを示すマッピングを設定する必要があります:

123456789
curl -XPOST localhost:9200/authors/nested_author/_mapping -d '{ "nested_author":{ "properties":{ "books": { "type": "nested" } } }}'

この新しいインデックスに以前と同じデータを挿入すると、このクエリ

ここでnestedフィルタを使用すると、ネストされた文書(つまり書籍)に対してクエリを実行し、クエリに一致する少なくとも一つのネストされた文書を持つものによって著者をフィルタリングすることができます。 pathオプションは、このクエリが適用される著者ドキュメントのどの部分に指示し、queryオプションは、これらのネストされたドキュメントに対して実行す 前のクエリとは異なり、これは両方の要件を満たす個々の本を見つける必要があるため、Alaistair Reynoldsだけが返されます

Parent&child

elasticsearchが提供する他の概念は、ドキ 前の例では、著者を親文書として、書籍を子文書として再加工することができます。

今回は、著者を書籍とは別に索引付けします。

次に、書籍タイプのマッピングを設定し、その親タイプがbare_authorであるとします。 本を作成する前にこれを行う必要があります。

12345
curl -XPOST localhost:9200/authors/book/_mapping -d '{ "book":{ "_parent": {"type": "bare_author"} }}'

本のインデックスを作成するときは、親のidを指定する必要があります(つまり、以前に作成された著者のidを指定します)

Elasticsearchは、tinに記載されている: これは、特定のクエリを満たす少なくとも一つの子を持つ親文書を選択します。 このクエリはAlastair Reynoldsのみを検索します:

Solr4.0は明らかに結合を行う能力を持っていますが、私が知る限り、これにはいくつかの制限がありますが、特に分散環境で操作されている場合は結合はありません。 親/子型の関係に自分自身を制限することにより、elasticsearchは自分自身の生活を楽にします:子は常に親と同じシャードで索引付けされるため、has_childは厄介なシャード

リストの構築

ユーザーが評価したアイテムが必要な場合など、共有グローバルアイテムのユーザー固有のリストをモデル化するためにも使用できます。 この場合、あなたの子ドキュメントは、特定のユーザーが特定の投稿を評価したという事実を表します-それらはuser_idpost_id、およびrating:aリレーショナルデータベースlingoの結合

親/子リレーションシップとhas_childを使用すると、ユーザーがお気に入りのすべての投稿を簡単に見つけることができ、投稿の内容、日付、その他の投稿の属性や子アイテムプロパティに基づいてお気に入りを検索することができます。 Rated itemsリストに項目を追加するのは安価です-それは非常に小さいrating項目の索引付けだけを必要とします。

これらのドキュメントを使用して

このクエリ

は、関心のあるユーザーによって3以上の評価されたボリビアに言及している唯一の投稿であるため、”bolivia rated4″のみを検索します。 Titleの最上位レベルのクエリは投稿に適用され、has_childフィルタ内のクエリは、子が一致する必要がある条件を記述します(この場合、子は特定のユーザーに属し、少

順序付け

has_childではできないのは、子の属性に基づいた順序または子の属性を返すことです。 ユーザーの評価された投稿をいつ評価されたか、評価を下げたかに基づいて注文したい場合は、投稿/評価に対して直接検索できますが、投稿にも検索クリテ たとえば、特定のトピックに関する評価された投稿のみを検索したい場合があります(ユーザーが与えた評価によって順序付けられています)。 has_childでは、あなたは運が悪いです。 ネストされた文書も助けにはなりません。

0.19.10以降はhas_parentフィルタを使用できます。 これは、子とほぼ同じように機能しますが、代わりに親アイテムに対するクエリを指定できます。 このクエリは、タイトルが”bolivia”に一致する投稿について、スコア順に

でユーザー1234による評価を返します。

それを偽造する

古いバージョンのelasticsearchに固執している場合は、top_childrenでほとんどの方法を得ることができます。 ドキュメントによると、top_childrenは最初に子ドキュメントを照会し、次にそれらを親ドキュメントに集約します。 この例では、これはelasticsearchが最初にクエリに一致する評価ドキュメントを見つけることを意味します。 次に、各評価を親の投稿に一致させ、重複した投稿が存在する場所に集約します。

トップの子を持つ厄介なビットは、elasticsearchが集計が発生したときに失うドキュメントの数を事前に知らないということです。 この特定のケースでは、同じユーザーによる2つの異なる評価が常に2つの異なる投稿に対応するため、集約フェーズが何もしないため、factorincremental_factorの設定を気に 同様に、スコアモードも重要ではありません。 結果の総数の正確なカウントを提供する必要がある場合は、elasticsearchが子ドキュメントの最初のスイープですべてを検出するのに十分な大きさfactorを設定す ユーザーがリストに500の評価項目を持っていて、最初の10項目を求めていることがわかっている場合は、50の係数がトリックを行う必要があります。 ユーザーがリストに持っているアイテムの数を正確に知る必要はありません(ユーザーが評価の特定のサブセットを検索している場合は、個別のelastic searchクエ

この後に得られるのは、子ドキュメントのクエリスコア(評価)でソートされた親ドキュメント(投稿)のリストです。 子ドキュメントの属性に基づいて投稿をソートするという当初の目標を達成するには、このクエリスコアが正しい値を持つことを確認するだけです。 たとえば、top_childrenクエリでcustom_scoreクエリをラップして、各子のスコアを制御できるようにします。

インデックス内の同じドキュメントを使用すると、このクエリはユーザー1234が評価した投稿を、評価順に返します:

私たちはtop_childrenクエリを実行しているので、最初に行う必要があるのは、私たちが検討している子供のタイプ(評価)が何であるかを言うことです。 次に、それらの子を見つけるクエリを提供します。 これはcustom_scoreクエリで、filteredクエリをラップします。 filteredクエリは、関心のあるユーザーによって与えられた評価のみを見つけ、script要素は評価ドキュメントのスコアを評価自体にするため、投稿を評価でソートします。 バックスラッシュのfunkinessは、単一引用符で区切られたシェルフレンドリな文字列にリテラルの単一引用符を含めようとしているためです-私たちが送

Ruby fun

残念ながら、tireライブラリは現時点ではこの楽しいものを実際にサポートしていません-現時点では、すべての小さなクエリタイプとオプションがtireに散らばっている別々のメソッドになってしまうため、この種の機能が追加されています。 あなたはそれをハックすることができます。

Tireでは、インデックス作成時にドキュメントの親idを設定することはできません。 これは追加するのは簡単で、前述のモラトリアムによってのみ開催されています。 私のフォークはこの能力を追加します。 それで、あなたは

で終わる不幸の次のビットは、tireの自動インデックス作成はインデックスごとに1つのタイプを前提としていますが、親/子の関係が存在するためには、両方のタイプが同じインデックスになければならないということです。 私はインデックスを作成するためにこのようなことをやってしまいました。

これはそれほど美しくはありませんが、仕事を終わらせます。

最後に、実際にクエリを実行する必要があります。 実際にtireのapiの一部であるtop_childrenがない場合、

のようにファッジすることができます。

この少しの不快感は、ハッシュとしてクエリを構築し、それをtireに押し込 明らかに、他の条件(投稿または評価のいずれか)を検索に簡単に追加できるように構造化することができます。 Jsonを手動でビルドしてPost.search :payload => my_jsonを使用することもできます(tire-contribのlogger拡張機能と衝突するpayloadオプションにバグがあります)

コメントを残す

メールアドレスが公開されることはありません。