【问题标题】:unable to use $match operator for mongodb/mongoose aggregation with ObjectId无法将 $match 运算符用于带有 ObjectId 的 mongodb/mongoose 聚合
【发布时间】:2013-04-25 00:07:38
【问题描述】:

相对简单的场景:

我有这个Voucher 对象,它有一个user 属性(ObjectId 类型)。我想获取单个用户的所有凭证值的总和。这是我当前的策略,它返回一个空数组:

Voucher.aggregate [
    { $match : { user : new ObjectId(user_id), expires : { $gt : new Date() } } }
    { $group : { _id : null, sum : { $sum : '$value' } } }
], (err, result)->

    console.log err
    console.log result

删除user id 的匹配项并保留expires 字段将返回结果。那么问题就变成了user上的匹配有什么问题?

【问题讨论】:

  • 我无法重现这个; $match 在普通的 mongo shell 中使用 ObjectId 为我工作。我不知道你代码块中的dc 是什么。那是猫鼬的事吗?
  • 具体来说,这是我在 mongo shell 中所做的:在我的测试数据库中,我做了db.tmp.save({foo: ObjectId()})。然后在用findOne 找到它的ID 后,我做了db.users.aggregate({$match:{foo:ObjectId("5180956a55064fce4d42f02d")}}) 并在结果中返回了该文档。您可以试试这个,然后尝试将您的问题减少到问题的最小示例吗?顺便说一句,我正在使用 Mongo 2.4.3。
  • 嗨,道格,感谢您的帮助。 dc 是一个带有一些助手(如对象 ID)的上下文对象。所以请忽略这一点。我将聚合减少到 { $match : { user : new ObjectId(user_id) } } 并且仍然收到 [] 的结果。
  • 在 mongo shell 中运行相同的聚合是有效的。
  • 感谢Doug的帮助,最终让我找到了错误。

标签: mongodb mongoose aggregation-framework


【解决方案1】:

原来 ObjectId 的转换似乎是问题所在。当它需要只是一个纯 ObjectId mongoose.Types.ObjectId 时,它使用 Schema 类型 Object Id mongoose.Schema.Types.ObjectId 进行转换。

【讨论】:

  • +1。我只是被这个咬了。感谢您的回答!
  • 谢谢一堆.. 至少我的头上还有头发:( 你救了我 xD
【解决方案2】:

当使用 find 方法或 findById 时,查询只能是:

var query = {
    $or: [
        {'_sender':req.body._id},
        {'_recipient':req.body._id}
    ]
};

当使用聚合时,查询需要强制转换

var mongoose = require('mongoose');
var query = {
    $or: [
        {'_sender':new mongoose.Types.ObjectId(decoded._id)},
        {'_recipient':new mongoose.Types.ObjectId(decoded._id)}
    ]
};

【讨论】:

  • 不要只发布代码。请添加说明为什么此代码可以解决问题。
  • 这拯救了我的一天! +1
【解决方案3】:
var aggregate  = [
{
                $match: {
                    'lenderId': new mongoose.Types.ObjectId(req.user),
                    '_disbursed': true
                }
            },
            {
                $unwind:'$emi'
            },
            {
                $match: {
                    'emi._settled': false,
                }
            }
];

【讨论】:

  • 您好,欢迎来到 SO!尽管代码本身可能会说话,但提供一些细节将有助于提高您的答案质量!
【解决方案4】:

使用 toString() 方法。

{ $match : { user : user_id.toString() , expires : { $gt : new Date() } } }

【讨论】:

    猜你喜欢
    • 2017-08-03
    • 2015-05-25
    • 2013-07-18
    • 1970-01-01
    • 2017-09-13
    • 2014-12-11
    • 1970-01-01
    • 2016-04-10
    • 2017-01-16
    相关资源
    最近更新 更多