11

私のmongoDBブックコレクションには、次のように構成されたドキュメントがあります。

/* 0 */
{
  "_id" : ObjectId("50485b89b30f1ea69110ff4c"),

  "publisher" : {
    "$ref" : "boohya",
    "$id" : "foo"
  },
  "displayName" : "Paris Nightlife",
  "catalogDescription" : "Some desc goes here",
  "languageCode" : "en",
  "rating" : 0,
  "status" : "LIVE",
  "thumbnailId" : ObjectId("50485b89b30f1ea69110ff4b"),
  "indexTokens" : ["Nightlife", "Paris"]
}

次の正規表現クエリを実行して、「Par」で始まる1つのindexTokenを持つすべてのドキュメントを検索します。

{ "indexTokens" : { "$regex" : "^Par" , "$options" : "i"}}

次のように返されるindexTokensフィールドのみを選択した場合:

{ "indexTokens" : 1}

結果のDBObjectは

{ "_id" : { "$oid" : "50485b89b30f1ea69110ff4c"} , "indexTokens" : [ "Nightlife" , "Paris"]}

取得したいのは、正規表現に一致するトークン/タグのみです(この時点でドキュメントを取得する必要はありません。一致するドキュメントのすべてのタグも必要ありません)。

これは、MongoDBv2.2でリリースされた新しいアグリゲーションフレームワークの場合ですか。?

はいの場合、実際の結果が次のようになるようにクエリを変更するにはどうすればよいですか。

{"indexTokens":["Paris"、 "Paradise River"、"Parma"など....]}

ボーナスの質問(codezはありますか):Javaドライバーを使用してそれを行うにはどうすればよいですか?

今のところ私のJavaは次のようになります:

DBObject query = new BasicDBObject("indexTokens", java.util.regex.Pattern.compile("^"+filter+"", Pattern.CASE_INSENSITIVE));
    BasicDBObject fields = new BasicDBObject("indexTokens",1);
    DBCursor curs = getCollection()
                    .find(query, fields)
                    .sort( new BasicDBObject( "indexTokens" , 1 ))
                    .limit(maxSuggestionCount);

どうも :)

編集:

あなたの答えに従って、私は次のように私のJAVAコードを変更しました:

BasicDBObject cmdBody = new BasicDBObject("aggregate", "Book"); 
    ArrayList<BasicDBObject> pipeline = new ArrayList<BasicDBObject>(); 

    BasicDBObject match = new BasicDBObject("$match", new BasicDBObject("indexTokens", java.util.regex.Pattern.compile("^"+titleFilter+"", Pattern.CASE_INSENSITIVE)));
    BasicDBObject unwind = new BasicDBObject("$unwind", "$indexTokens");
    BasicDBObject match2 = new BasicDBObject("$match", new BasicDBObject("indexTokens", java.util.regex.Pattern.compile("^"+titleFilter+"", Pattern.CASE_INSENSITIVE)));
    BasicDBObject groupFilters = new BasicDBObject("_id",null);
    groupFilters.append("indexTokens", new BasicDBObject( "$push", "$indexTokens"));
    BasicDBObject group = new BasicDBObject("$group", groupFilters);

    pipeline.add(match);
    pipeline.add(unwind);
    pipeline.add(match2);
    pipeline.add(group);

    cmdBody.put("pipeline", pipeline); 



    CommandResult res = getCollection().getDB().command(cmdBody);
    System.out.println(res);

どの出力

{ "result" : [ { "_id" :  null  , "indexTokens" : [ "Paris"]}] , "ok" : 1.0}

これは天才です!

どうもありがとう !

4

2 に答える 2

11

これは、2.2集約フレームワークを使用して行うことができます。このようなもの;

db.books.runCommand("aggregate", {
    pipeline: [
        {   // find docs that contain Par*
            $match: { "indexTokens" : { "$regex" : "^Par" , "$options" : "i"}},
        },
        {   // create a doc with a single array elemm for each indexToken entry
            $unwind: "$indexTokens" 
        },
        {   // now produce a list of index tokens
            $group: {
                _id: "$indexTokens",
            },
        },
    ],
})

または、ドキュメントなしでアレイが本当に必要な場合は、これはあなたが求めているものにさらに近いかもしれません。

db.books.runCommand("aggregate", {
    pipeline: [
        {   // find docs that contain Par*
            $match: { "indexTokens" : { "$regex" : "^Par" , "$options" : "i"}},
        },
        {   // create a doc with a single array elemm for each indexToken entry
            $unwind: "$indexTokens" 
        },
        {   // now throw out any unwind's that DON'T contain Par*
            $match: { "indexTokens": { "$regex": "^Par", "$options": "i" } },
        },
        {   // now produce the list of index tokens
            $group: {
                _id: null,
                indexTokens: { $push: "$indexTokens" },
            },
        },
    ],
})
于 2012-09-06T10:43:42.343 に答える
4

cirrusからの応答に基づいて$unwind、冗長性を回避するために最初に実行することをお勧めします$match。何かのようなもの:

db.books.aggregate(
    {$unwind:"$indexTokens"},
    {$match:{indexTokens:/^Par/}},
    {$group:{_id:null,indexTokens:{$push:"$indexTokens"}}
})

Javaでこれをどのように行いますか?DBCollection.aggregate(...)MongoDBv2.9.0ドライバーのメソッドを使用できます。各パイプラインオペレーター、例えば。$unwindまたは$matchDBObjectオブジェクトに対応します。

于 2012-09-06T13:51:58.307 に答える