Mongodb聚合: How to return only matching elements of an array

标签 mongodb aggregation-framework

在我的 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”开头的一个indexToken的所有文档:

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

如果我只选择要返回的 indexTokens 字段,如下所示:

{ "indexTokens" : 1}

生成的 DBObject 是

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

我想要得到的只是与正则表达式匹配的 token /标签(此时我不关心检索文档,也不需要匹配文档的所有标签)

这是 MongoDB v2.2 下发布的新聚合框架的情况吗? ?

如果是,我如何修改我的查询以使实际结果看起来像:

{ "indexTokens": ["巴黎"、"天堂河"、"帕尔马"等....]}

额外问题(您有代码吗):我如何使用 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}

这真是天才!

非常感谢!

最佳答案

您可以使用 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" },
            },
        },
    ],
})

关于Mongodb聚合: How to return only matching elements of an array,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12296963/

相关文章:

mongodb - 过滤器内的 $eq 不适用于数组字段 - Mongodb

javascript - 获取数字的 CastError NaN

mongodb - Meteor find().fetch() 与多个条件不工作

mongodb - 返回每组的最后一个 "true"值

Mongodb图查找

MongoDB 基于间隔分组

mongodb - 如何在 elasticsearch 中为 mongo-connector 生成的索引创建映射

mongodb - 使用 Rust 更新 MongoDB 中的数据

node.js - mongoose 不会获取更新的数据,除非重新启动nodejs

Mongodb聚合-排序使得查询非常慢