MongoDB:使用ObjectId数组进行$in操作

14

关于我刚经历过的事情,我有一个简短的问题,并且我仍在思考为什么:

mongos> db.tickets.count({ "idReferenceList" : { "$in" : [ { "$oid" : "53f1f09f2cdcc8f339e5efa2"} , { "$oid" : "5409ae2e2cdc31c5aa0ce0a5"}]}});

0

mongos> db.tickets.count({ "idReferenceList" : { "$in" : [ ObjectId("53f1f09f2cdcc8f339e5efa2") , ObjectId("5409ae2e2cdc31c5aa0ce0a5")]}});

我曾以为在MongoDB中$oid和ObjectId拼写格式完全相同。有人知道为什么第一个查询返回0个结果,而第二个查询返回2个结果(正确的答案)吗?

此外,我正在使用Morphia框架与MongoDB交互,该框架使用MongoDB Java驱动程序。我意识到当在非_id字段上的ObjectIds数组中使用$in操作符进行搜索时存在问题,通过执行以下代码行来解决:

List< ObjectId > fParams = new ArrayList< ObjectId >();

fParams.add(...);

Query<Ticket> query = genericDAO.createQuery();

query.field("idReferenceList").in(fParams);

result = genericDAO.find(query).asList();

非常感谢您的支持。

敬礼,

  • Luis Cappa

1
genericDAO.find(query).asList(); // 你能做到并检查一下吗?顺便问一下,你在使用这个.createQuery(filter)中的过滤器是什么? - BatScream
抱歉,那只是一个打错字的错误。'createQuery'方法是一个内部方法,它通过fParams列表进行过滤来创建查询。简而言之,genericDAO.Find(this.createQuery(filter))与genericDAO.find(query)是相同的。对此很抱歉。 - lcappa
2个回答

8
这两种格式都是MongoDB中对象ID的有效表示,根据文档说明,http://docs.mongodb.org/manual/reference/mongodb-extended-json/。在这两种模式下,它们的表示方式不同。
    Strict Mode         mongo Shell Mode
    -----------         ----------------

   { "$oid": "<id>" }  ObjectId( "<id>" )

因此,要查询包含objectid的字段,在shell/console模式下,您需要使用ObjectId("<id>"),这是在mongo shell模式下需要遵循的语法。
因此,以下查询:
db.tickets.count({ "idReferenceList" : { "$in" : [ ObjectId("53f1f09f2cdcc8f339e5efa2") , ObjectId("5409ae2e2cdc31c5aa0ce0a5")]}});

会返回行数。

现在通过Java API实现它,

你需要按照以下方法进行:

String[] ids = {"53f1f09f2cdcc8f339e5efa2","5409ae2e2cdc31c5aa0ce0a5"};
ObjectId[] objarray = new ObjectId[ids.length];

for(int i=0;i<ids.length;i++)
{
    objarray[i] = new ObjectId(ids[i]);
}

BasicDBObject inQuery = new BasicDBObject("$in", objarray);
BasicDBObject query = new BasicDBObject("idReferenceList", inQuery);
DBCursor cursor = db.collection.find(query);
while(cursor.hasNext())
{
    DBObject doc = cursor.next();
    // process the doc.
}

问题在于我不是在查询“_id”字段,而是在查询“idReferenceList”,这是另一个不同的字段,定义为对象ID数组类型。正如你所看到的,这并不起作用... - lcappa
objectid的表示方式不受其所在字段的影响而保持不变。我会更新我的答案。我只是给出了_id字段的一个参考。 - BatScream
但是使用"$oid"表示法不起作用。你测试过了吗?只需通过shell保存两个测试文档并自行尝试。问题在于我正在使用MongoDB Java驱动程序,我无法直接拼写"ObjectId"查询格式。 - lcappa
是的,请仔细阅读我的答案。在 shell 中,$oid 表示不起作用,因为它是在严格模式下遵循的语法。 - BatScream
这个链接可能会对你有所帮助:https://groups.google.com/forum/m/#!topic/mongodb-user/YNrVuv1wGGw - BatScream
显示剩余3条评论

4

我遇到了同样的问题。 我像这样解决了它。

db.collection('post').find({ 'postIds': { $elemMatch: { $in:
deletedPosts.map(_post => {ObjectId(_post._id)}) } } })

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接