ネストされた子ドキュメントの検索
このセクションでは、深くネストされたドキュメントを検索するために使用できる潜在的なテクニックを紹介し、Solr のクエリパーサーとドキュメントトランスフォーマーを使用して、より複雑なクエリをどのように構築できるかを示します。
これらの機能を使用するには、スキーマで _root_
と _nest_path_
を宣言する必要があります。スキーマとインデックスの構成の詳細については、ネストされたドキュメントのインデクシング を参照してください。
このセクションでは、ネストされたドキュメントのファセットについては説明していません。ネストされたドキュメントのファセットについては、ブロック結合ファセットカウント セクションを参照してください。 |
クエリ例
今後の例では、ネストされたドキュメントのインデクシング で説明されているのと同じドキュメントを含むインデックスを想定します。
[{ "id": "P11!prod",
"name_s": "Swingline Stapler",
"description_t": "The Cadillac of office staplers ...",
"skus": [ { "id": "P11!S21",
"color_s": "RED",
"price_i": 42,
"manuals": [ { "id": "P11!D41",
"name_s": "Red Swingline Brochure",
"pages_i":1,
"content_t": "..."
} ]
},
{ "id": "P11!S31",
"color_s": "BLACK",
"price_i": 3
} ],
"manuals": [ { "id": "P11!D51",
"name_s": "Quick Reference Guide",
"pages_i":1,
"content_t": "How to use your stapler ..."
},
{ "id": "P11!D61",
"name_s": "Warranty Details",
"pages_i":42,
"content_t": "... lifetime guarantee ..."
} ]
},
{ "id": "P22!prod",
"name_s": "Mont Blanc Fountain Pen",
"description_t": "A Premium Writing Instrument ...",
"skus": [ { "id": "P22!S22",
"color_s": "RED",
"price_i": 89,
"manuals": [ { "id": "P22!D42",
"name_s": "Red Mont Blanc Brochure",
"pages_i":1,
"content_t": "..."
} ]
},
{ "id": "P22!S32",
"color_s": "BLACK",
"price_i": 67
} ],
"manuals": [ { "id": "P22!D52",
"name_s": "How To Use A Pen",
"pages_i":42,
"content_t": "Start by removing the cap ..."
} ]
} ]
子ドキュメントトランスフォーマー
デフォルトでは、クエリに一致するドキュメントには、レスポンスにネストされた子が含まれていません。[child]
ドキュメントトランスフォーマーを使用すると、クエリ結果をドキュメントの子孫でエンリッチできます。
このトランスフォーマーの詳細な説明、および構文と制限事項の詳細については、[child - ChildDocTransformerFactory] セクションを参照してください。
「staplers」を含む説明を持つすべてのドキュメントに一致する単純なクエリ
$ curl 'https://127.0.0.1:8983/solr/gettingstarted/select?omitHeader=true&q=description_t:staplers'
{
"response":{"numFound":1,"start":0,"maxScore":0.30136836,"numFoundExact":true,"docs":[
{
"id":"P11!prod",
"name_s":"Swingline Stapler",
"description_t":"The Cadillac of office staplers ...",
"_version_":1672933224035123200}]
}}
[child]
トランスフォーマーを追加した同じクエリを以下に示します。numFound
は変更されておらず、まだ同じドキュメントセットに一致していることに注意してください。ただし、これらのドキュメントを返す場合は、ネストされた子も疑似フィールドとして返されます。
$ curl 'https://127.0.0.1:8983/solr/gettingstarted/select?omitHeader=true&q=description_t:staplers&fl=*,[child]'
{
"response":{"numFound":1,"start":0,"maxScore":0.30136836,"numFoundExact":true,"docs":[
{
"id":"P11!prod",
"name_s":"Swingline Stapler",
"description_t":"The Cadillac of office staplers ...",
"_version_":1672933224035123200,
"skus":[
{
"id":"P11!S21",
"color_s":"RED",
"price_i":42,
"_version_":1672933224035123200,
"manuals":[
{
"id":"P11!D41",
"name_s":"Red Swingline Brochure",
"pages_i":1,
"content_t":"...",
"_version_":1672933224035123200}]},
{
"id":"P11!S31",
"color_s":"BLACK",
"price_i":3,
"_version_":1672933224035123200}],
"manuals":[
{
"id":"P11!D51",
"name_s":"Quick Reference Guide",
"pages_i":1,
"content_t":"How to use your stapler ...",
"_version_":1672933224035123200},
{
"id":"P11!D61",
"name_s":"Warranty Details",
"pages_i":42,
"content_t":"... lifetime guarantee ...",
"_version_":1672933224035123200}]}]
}}
子クエリパーサー
{!child}
クエリパーサーを使用すると、ラップされたクエリに一致する親ドキュメントの*子孫*ドキュメントを検索できます。このパーサーの詳細な説明については、ブロック結合子クエリパーサー セクションを参照してください。
上記で使用した description_t:staplers
クエリをもう一度考えてみましょう。このクエリを {!child}
クエリパーサーでラップすると、製品レベルのドキュメントを「一致」させて返す代わりに、元のクエリの*子孫*すべての子ドキュメントに一致します。
$ curl 'https://127.0.0.1:8983/solr/gettingstarted/select' -d 'omitHeader=true' -d 'q={!child of="*:* -_nest_path_:*"}description_t:staplers'
{
"response":{"numFound":5,"start":0,"maxScore":0.30136836,"numFoundExact":true,"docs":[
{
"id":"P11!D41",
"name_s":"Red Swingline Brochure",
"pages_i":1,
"content_t":"...",
"_version_":1672933224035123200},
{
"id":"P11!S21",
"color_s":"RED",
"price_i":42,
"_version_":1672933224035123200},
{
"id":"P11!S31",
"color_s":"BLACK",
"price_i":3,
"_version_":1672933224035123200},
{
"id":"P11!D51",
"name_s":"Quick Reference Guide",
"pages_i":1,
"content_t":"How to use your stapler ...",
"_version_":1672933224035123200},
{
"id":"P11!D61",
"name_s":"Warranty Details",
"pages_i":42,
"content_t":"... lifetime guarantee ...",
"_version_":1672933224035123200}]
}}
この例では、of
パラメータとして *:* -_nest_path_:*
を使用して、ネストパスを持たないすべてのドキュメント、つまりすべての「ルート」レベルのドキュメントを、可能な親のセットとして扱うことを示しています。
of
パラメータを変更して特定の _nest_path_
レベルの祖先に一致させることにより、返す子のリストを絞り込むことができます。以下のクエリでは、/skus/*
のプレフィックスを持つ _nest_path_
を*持たない*すべてのドキュメントを識別する of
パラメータを使用して、skus
のすべての子孫を検索し、price_i
が 50
未満です。
$ curl 'https://127.0.0.1:8983/solr/gettingstarted/select' -d 'omitHeader=true' --data-urlencode 'q={!child of="*:* -_nest_path_:\\/skus\\/*"}(+price_i:[* TO 50] +_nest_path_:\/skus)'
{
"response":{"numFound":1,"start":0,"maxScore":1.0,"numFoundExact":true,"docs":[
{
"id":"P11!D41",
"name_s":"Red Swingline Brochure",
"pages_i":1,
"content_t":"...",
"_version_":1675662666752851968}]
}}
of での _nest_path_ スラッシュの二重エスケープ上記の例では、
(クエリ文字列の本文では、正規表現構文を防ぐために、1レベルの
|
親クエリパーサー
{!child}
クエリパーサーの逆は {!parent}
クエリパーサーです。これは、ラップされたクエリに一致する子ドキュメントの *祖先* ドキュメントを検索できます。このパーサーの詳細な説明については、ブロック結合親クエリパーサー のセクションを参照してください。
最初に、正確に 1
ページを持つすべての「マニュアル」タイプのドキュメントを検索するこの例を考えてみましょう。
$ curl 'https://127.0.0.1:8983/solr/gettingstarted/select?omitHeader=true&q=pages_i:1'
{
"response":{"numFound":3,"start":0,"maxScore":1.0,"numFoundExact":true,"docs":[
{
"id":"P11!D41",
"name_s":"Red Swingline Brochure",
"pages_i":1,
"content_t":"...",
"_version_":1676585794196733952},
{
"id":"P11!D51",
"name_s":"Quick Reference Guide",
"pages_i":1,
"content_t":"How to use your stapler ...",
"_version_":1676585794196733952},
{
"id":"P22!D42",
"name_s":"Red Mont Blanc Brochure",
"pages_i":1,
"content_t":"...",
"_version_":1676585794347728896}]
}}
そのクエリを {!parent}
クエリでラップして、これらのマニュアルの祖先であるすべての製品の詳細を返すことができます。
$ curl 'https://127.0.0.1:8983/solr/gettingstarted/select' -d 'omitHeader=true' --data-urlencode 'q={!parent which="*:* -_nest_path_:*"}(+_nest_path_:\/skus\/manuals +pages_i:1)'
{
"response":{"numFound":2,"start":0,"maxScore":1.4E-45,"numFoundExact":true,"docs":[
{
"id":"P11!prod",
"name_s":"Swingline Stapler",
"description_t":"The Cadillac of office staplers ...",
"_version_":1676585794196733952},
{
"id":"P22!prod",
"name_s":"Mont Blanc Fountain Pen",
"description_t":"A Premium Writing Instrument ...",
"_version_":1676585794347728896}]
}}
この例では、which
パラメータ として *:* -_nest_path_:*
を使用して、ネストパスを持たないすべてのドキュメント、つまりすべての「ルート」レベルのドキュメントを、可能な親のセットとして考慮することを示しています。
which
パラメータを変更して特定の _nest_path_
レベルの祖先に一致させることで、返す祖先のタイプを変更できます。以下のクエリでは、正確に 1
ページのマニュアルの祖先である sku
(/skus/*
というプレフィックスを持つ _nest_path_
を *持たない* すべてのドキュメントを識別する which
パラメータを使用)を検索します。
$ curl 'https://127.0.0.1:8983/solr/gettingstarted/select' -d 'omitHeader=true' --data-urlencode 'q={!parent which="*:* -_nest_path_:\\/skus\\/*"}(+_nest_path_:\/skus\/manuals +pages_i:1)'
{
"response":{"numFound":2,"start":0,"maxScore":1.4E-45,"numFoundExact":true,"docs":[
{
"id":"P11!S21",
"color_s":"RED",
"price_i":42,
"_version_":1676585794196733952},
{
"id":"P22!S22",
"color_s":"RED",
"price_i":89,
"_version_":1676585794347728896}]
}}
上記の例では、 |
ブロック結合クエリパーサーと子ドキュメントトランスフォーマーの組み合わせ
これらの2つのパーサーと `[child]` トランスフォーマーの組み合わせにより、非常に強力なクエリをシームレスに作成できます。
たとえば、次のようなクエリがあります。
-
返される(sku)ドキュメントの色は「RED」である必要があります。
-
返される(sku)ドキュメントは、次の条件を持つルートレベル(製品)ドキュメントの子孫である必要があります。
-
コンテンツに「lifetime guarantee」を含む直接の子「マニュアル」ドキュメントを持つ
-
各リターン(sku)ドキュメントには、それが持つ子孫(マニュアル)ドキュメントも含まれます。
-
-
$ curl 'https://127.0.0.1:8983/solr/gettingstarted/select' -d 'omitHeader=true' -d 'fq=color_s:RED' --data-urlencode 'q={!child of="*:* -_nest_path_:*" filters=$parent_fq}' --data-urlencode 'parent_fq={!parent which="*:* -_nest_path_:*"}(+_nest_path_:"/manuals" +content_t:"lifetime guarantee")' -d 'fl=*,[child]'
{
"response":{"numFound":1,"start":0,"maxScore":1.4E-45,"numFoundExact":true,"docs":[
{
"id":"P11!S21",
"color_s":"RED",
"price_i":42,
"_version_":1676585794196733952,
"manuals":[
{
"id":"P11!D41",
"name_s":"Red Swingline Brochure",
"pages_i":1,
"content_t":"...",
"_version_":1676585794196733952}]}]
}}