如何从mongo中找到所选的数组元素

时间:2015-05-26 19:23:06

标签: java mongodb mongo-java

我想只找到mongo文档中的select数组元素。在下面的文档中我想只返回数组中的难题。 我正在使用mongo驱动程序的java。

BasicDBObject query=new BasicDBObject("questionList.type", "hard");
DBCursor curssc  = collection.find(query);

文档

{
   "testpaperid": 1,
   "testpaperNo": "science",
   "questionList":
      [
         {
            "question": "this is question no 1",
            "type": "hard"
         },
         {
            "question": "this is question no 2",
            "type":"simple"
         },
         {
            "question": "this is question no 3",
            "type": "hard"
         }
      ] 
}

2 个答案:

答案 0 :(得分:3)

如果使用$elemMatch运算符,它会将查询结果中<array>字段的内容限制为仅包含与$elemMatch条件匹配的第一个元素。

所以如果你运行这个查询:

db.collectionName.find({"questionList":{"$elemMatch":{"type":"hard"}}},{"questionList.type.$":1})

及以上查询java中的等效代码如下:

BasicDBObject eleMatch = new BasicDBObject();
eleMatch.put("type", "hard");
BasicDBObject elemMatchQuery = new BasicDBObject();
elemMatchQuery.put("$elemMatch", eleMatch);
BasicDBObject query = new BasicDBObject();
query.put("questionList", elemMatchQuery);
BasicDBObject projection = new BasicDBObject();
projection.put("questionList.type.$", 1);
DBCollection dbcoll = mongoTemplate.getCollection("collectionName");
DBObject object = dbcoll.find(query, projection);

此返回仅第一个匹配的type:hard输出包含"questionList" : [ { "question" : "this is question no 1", "type" : "hard" } ]并非包含questionList的所有type:hard数组

为了避免这种情况,请使用mongo java aggregation driver和mongo聚合查询,如下所示:

db.collectionName.aggregate({
  "$unwind": "$questionList"
}, {
  "$match": {
    "questionList.type": "hard"
  }
}, {
  "$group": {
    "_id": "$_id",
    "testpaperid": {
      "$first": "$testpaperid"
    },
    "testpaperNo": {
      "$first": "$testpaperNo"
    },
    "questionList": {
      "$push": "$questionList"
    }
  }
}).pretty()

和java中的聚合查询如下:

// unwind  questionList
DBObject unwind = new BasicDBObject("$unwind", "$questionList");
// create  pipeline operations, with the $match
DBObject match = new BasicDBObject("$match", new BasicDBObject("questionList.type", "hard"));
// Now the $group operation  
DBObject groupFields = new BasicDBObject("_id", "$group field");
groupFields.put("testpaperid", new BasicDBObject("$first", "$testpaperid"));
groupFields.put("testpaperNo", new BasicDBObject("$first", "$testpaperNo"));
groupFields.put("questionList", new BasicDBObject("$push", "$questionList"));
DBObject group = new BasicDBObject("$group", groupFields);
// run aggregation
List < DBObject > pipeline = Arrays.asList(unwind, match, group);
AggregationOutput output = collectionName.aggregate(pipeline);
for(DBObject result: output.results()) {
  System.out.println(result);
}

答案 1 :(得分:0)

当您在MongoDB中的常规查询中使用array operators时,它会返回与查询条件匹配的文档,并返回整个文档,包括数组字段的内容。这意味着您无法使用常规查询从数组字段中过滤掉某些文档。

但你可以使用aggregation query来做到这一点。以下查询是mongo-shell的聚合查询,您可以轻松地将其转换为Java驱动程序代码:

def readData(path):
    rv = []
    with open(path, 'r') as file:
        for line in file:
            words = line.split()
            rv.append(words)
    return rv