2
{
"batters":
    {
    "batter":[
            { "id": "1001", "type": "Regular" },
            { "id": "1002", "type": "Chocolate" },
            { "id": "1003", "type": "Blueberry" },
            { "id": "1004", "type": "Devil's Food" }
    ]
    },
    "topping":[
            { "id": "5001", "type": "None" },
            { "id": "5002", "type": "Glazed" },
            { "id": "5005", "type": "Sugar" },
            { "id": "5007", "type": "Powdered Sugar" },
            { "id": "5006", "type": "Chocolate with Sprinkles" },
            { "id": "5003", "type": "Chocolate" },
            { "id": "5004", "type": "Maple" }
     ]
}

基本的に、ここで全文検索を行うには、「batters.batter」と「batters.topping」、つまり 2 つの属性でインデックスを作成する必要があります。この種の全文検索を処理する方法。メソッドについて説明してください。REST API を介して検索を実装したいと思います。よろしくお願いします。

4

1 に答える 1

5

これを解決する最善の方法は、データ レイアウトを少し変更することです。フルテキスト インデックスは 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"})
于 2016-01-15T13:50:58.670 に答える