复杂的MongoDB在Java中查找大型文档的查询

时间:2014-12-22 20:32:30

标签: java mongodb

当我希望查找包含嵌套文档数组的所有文档时,如何使用Java中的BasicDBObjects进行MongoDB查询,其中一个嵌套文档符合所有指定条件?

以示例数据为例:

[
   {
      "_id":"blood_0",
      "type":"O",
      "list":[
         {
            "firstname":"John",
            "lastname":"Smith",
            "zipcode":"12345"
         },
         {
            "firstname":"John",
            "lastname":"Hamilton",
            "zipcode":"54627"
         },
         {
            "firstname":"Ben",
            "lastname":"Brick",
            "zipcode":"12345"
         },
         {
            "firstname":"William",
            "lastname":"Tell",
            "zipcode":"15487"
         }
      ]
   },
   {
      "_id":"blood_1",
      "type":"AB",
      "list":[
         {
            "firstname":"Mary",
            "lastname":"Smith",
            "zipcode":"12345"
         },
         {
            "firstname":"John",
            "lastname":"Henry",
            "zipcode":"54624"
         },
         {
            "firstname":"Jacob",
            "lastname":"Tell",
            "zipcode":"19283"
         },
         {
            "firstname":"William",
            "lastname":"Dirk",
            "zipcode":"15999"
         }
      ]
   }
]

如果我只想在符合 firstname = William 标准的列表中返回包含联系人的对象, lastname = Tell 我将如何进行那?我正在进行的查询不是对标准进行分组,因此我会得到两个结果,其中我实际上应该得到一个。

我如何进行相同的查询,同时检查 type = AB ,以及其他不会返回结果的标准?

2 个答案:

答案 0 :(得分:2)

您正在寻找$elemMatch运营商。它将查询运算符限制为值数组中的单个元素。

在shell中,您的查询将如下所示:

db.people.find( { list : { $elemMatch : { lastName:"Smith", firstName: "John" } } } )

添加血型:

db.people.find( { 
       type : "AB",
       list : { $elemMatch : { lastName:"Smith", firstName: "John" } } 
} )

使用Java驱动程序会有点冗长。

DBObject elemMatch = new BasicDBObject();
elemMatch.put("lastName","Smith");
elemMatch.put("firstName","John");

DBObject query = new BasicDBObject();
query.append( "type", "AB");
query.append( "list", elemMatch);

将该查询传递给集合中的一个find()方法,您应该获得所需的文档。

请注意,$ elemMatch查询运算符将返回整个文档,包括数组中的所有元素。有一个类似命名的投影运算符,用于将返回的数组元素限制为仅匹配的元素。

HTH - Rob。

答案 1 :(得分:0)

首先要做的事情。我真的认为你的模型是完全错误的。由于多种原因,嵌套数组可能会不稳定地增长:

  1. 如果在将新成员写入此阵列时文档超出了padding,则需要在数据文件中迁移文档。这是一项非常昂贵的操作,您希望尽可能地防止它。
  2. BSON文件限制为16MB。因此,根据血型,您只能拥有有限数量的人。
  3. 所有查询往往有点复杂,相应的代码更臃肿,因此更慢。
  4. 那怎么办?拿这些文件:

    {
      _id: ObjectId(),
      firstName: "Mary",
      lastName: "Smith",
      zip: "12345",
      bt: "AB"
    },
    {
      _id: ObjectId(),
      firstName: "John",
      lastName: "Smith",
      zip: "12345",
      bt: "0"
    }
    

    索引设置为

    db.people.ensureIndex({lastName:1,firstName:1})
    db.people.ensureIndex({bt:1})
    
    在MongoDB shell上,你可以得到你想要的东西

    db.people.find({ lastName:"Smith", firstName: "John"})
    

    db.people.find({ bt: "AB" })
    

    此查询例如转换为以下内容

    MongoClient client = new MongoClient("localhost");
    
    DB db = client.getDB("yourDB");
    DBCollection coll = db.getCollection("yourCollection");
    
    BasicDBOBject query = new BasicDBObject("bt","AB");
    DBCursor cursor = coll.find(query);
    
    try {
    
      while( cursor.hasNext() ) {
    
        System.out.println( cursor.next() );
    
      }
    
    } finally {
    
        cursor.close();
    
    }
    

    您可能会发现MongoDB introduction for working with a Java driver很有趣。