これを解決する最善の方法は、データ レイアウトを少し変更することです。フルテキスト インデックスは 1 つの属性でしか機能せず、インデックスを 2 回要求しても決して高速ではないからです。したがって、無名グラフを使用して文字列をオブジェクトに接続します。
したがって、2 つの (頂点) コレクション、1 つのエッジ コレクション、1 つの頂点コレクションをフルテキスト インデックスと共に作成します。
db._create("dishStrings")
db._createEdgeCollection("dishEdges")
db._create("dish")
db.dishStrings.ensureIndex({type: "fulltext", fields: [ "name" ]});
そして、関係を結び付けてドキュメントを保存します。とエッジ_key
の関係で頂点を参照するために使用される属性を使用します。_from
_to
db.dishStrings.save({"_key": "1001", "name": "Regular" , type: "Batter"});
db.dishStrings.save({"_key": "1002", "name": "Chocolate", type: "Batter" });
db.dishStrings.save({"_key": "1003", "name": "Blueberry", type: "Batter"});
db.dishStrings.save({"_key": "1004", "name": "Devil's Food", type: "Batter"});
db.dishStrings.save({"_key": "5001", "name": "None", type: "Topping"});
db.dishStrings.save({"_key": "5002", "name": "Glazed", type: "Topping"});
db.dishStrings.save({"_key": "5005", "name": "Sugar", type: "Topping"});
db.dishStrings.save({"_key": "5007", "name": "Powdered Sugar", type: "Topping"});
db.dishStrings.save({"_key": "5006", "name": "Chocolate with Sprinkles", type: "Topping"});
db.dishStrings.save({"_key": "5003", "name": "Chocolate", type: "Topping"});
db.dishStrings.save({"_key": "5004", "name": "Maple", type: "Topping"});
db.dishEdges.save("dishStrings/1001", "dish/batter", {tasty: true, type: "Batter"})
db.dishEdges.save("dishStrings/1002", "dish/batter", {tasty: true, type: "Batter"})
db.dishEdges.save("dishStrings/1003", "dish/batter", {tasty: true, type: "Batter"})
db.dishEdges.save("dishStrings/1004", "dish/batter", {tasty: true, type: "Batter"})
db.dishEdges.save("dishStrings/5001", "dish/batter", {tasty: true, type: "Topping"})
db.dishEdges.save("dishStrings/5002", "dish/batter", {tasty: true, type: "Topping"})
db.dishEdges.save("dishStrings/5003", "dish/batter", {tasty: true, type: "Topping"})
db.dishEdges.save("dishStrings/5004", "dish/batter", {tasty: true, type: "Topping"})
db.dishEdges.save("dishStrings/5005", "dish/batter", {tasty: true, type: "Topping"})
db.dishEdges.save("dishStrings/5006", "dish/batter", {tasty: true, type: "Topping"})
db.dishEdges.save("dishStrings/5007", "dish/batter", {tasty: true, type: "Topping"})
db.dish.save({_key: "batter", tasty: true})
フルテキスト インデックスが機能することを再確認します。
db._query("FOR oneDishStr IN FULLTEXT(dishStrings, 'name', 'Chocolate')" +
" RETURN oneDishStr").toArray()
(.toArray()
コンソールに結果が出力されます)
3 ヒット、1 バッター、2 トッピングが得られます。検索文字列には検証されていない文字列が含まれている可能性があるため、バインド変数を使用してインジェクションを回避します。
db._query("FOR oneDishStr IN FULLTEXT(dishStrings, 'name', @searchString) " +
" RETURN oneDishStr",
{searchString: "Chocolate"});
次に、接続された皿を見つけるためにエッジ リレーションを使用します。
db._query("FOR oneDishStr IN FULLTEXT(dishStrings, 'name', @searchString) "+
"RETURN {str: oneDishStr, " +
"dishes: NEIGHBORS(dishStrings, dishEdges, oneDishStr," +
" 'outbound')}",
{searchString: "Chocolate"})
これはグラフを使用する古い (2.7 までの) 方法でした。高速フィルターを使用したいので、これを新しい 2.8 構文に変換します。
db._query("FOR oneDishStr IN FULLTEXT(dishStrings, 'name', @searchString) " +
" FOR v IN 1..1 OUTBOUND oneDishStr dishEdges RETURN " +
" {str: oneDishStr, dish: v}",
{searchString: "Chocolate"})
どちらの場合でも、 の 3 つの全文検索ヒットのそれぞれに対して 1 つのトラバーサルを取得することがわかりますChocolate
。であるヒットだけに関心がToppings
あるので、タイプではないすべてのエッジをフィルタリングしますTopping
。
db._query("FOR oneDishStr IN FULLTEXT(dishStrings, 'name', @searchString) "+
" FOR v, e IN 1..1 OUTBOUND oneDishStr dishEdges " +
" FILTER e.type == 'Topping' " +
" RETURN {str: oneDishStr, dish: v}",
{searchString: "Chocolate"})