如何在管道聚合(mongoDB)中比较文档中的两个字段?

20

我有一个如下的文档:

{
  "user_id": NumberLong(1),
  "updated_at": ISODate("2016-11-17T09:35:56.200Z"),
  "created_at": ISODate("2016-11-17T09:35:07.981Z"),
  "banners": {
    "normal_x970h90": "/images/banners/4/582d79cb3aef567d64621be9/photo-1440700265116-fe3f91810d72.jpg",
    "normal_x468h60": "/images/banners/4/582d79cb3aef567d64621be9/photo-1433354359170-23a4ae7338c6.jpg",
    "normal_x120h600": "/images/banners/4/582d79cb3aef567d64621be9/photo-1452570053594-1b985d6ea890.jpg"
  },
  "name": "jghjghjghj",
  "budget": "2000",
  "plan": null,
  "daily_budget": "232323",
  "daily_budget_auto": "",
  "href": "qls2.ir",
  "targets": {
    "cats": [
      "fun",
      "news"
    ],
    "region": "inIran",
    "iran_states": null,
    "os": "all",
    "gold_network": true,
    "dont_show_between_1_n_8": true
  },
  "payment": {
    "bank": "mellat",
    "tax": "add"
  },
  "click_cost": "102000",
  "status": null
}

我想在查询其他参数时检查 budget 是否低于 click_cost

db.bcamp.aggregate(
    [
        {
            $match:{
                $and: [ 
                    {"targets.cats":{
                        "$in" : ["all"]
                        }
                    },

                    {"banners.normal_x970h90":{
                        "$exists":true
                        }
                    },

                    {"href": {
                        $nin: ["qls.ir"]
                        }
                    }
                ]
            }
        }
    ]).pretty();

我已经尝试了如下的比较方法:

db.bcamp.aggregate(
    [
        {$project: {ab: {$cmp: ['$budget','$clickcost']}}},
        {$match: {ab:{$gt:1}}}
    ]).pretty();

但是我得到了错误的结果,它总是返回4个文档,它们的预算可能大于也可能小于click_cost,这意味着它获取了错误的数据。

我该如何将这个比较添加到我的mongoDB管道中?

1个回答

43

问题不在于比较运算符,而在于您正在进行比较的值的类型。您应该将变量类型更改为数字。根据您的比较将匹配项更改为1、-1或0。

db.bcamp.aggregate(
[  {$project: {ab: {$cmp: ['$budget','$clickcost']}}},
  {$match: {ab:{$eq:1}}}
]).pretty();

您可以在3.6版本中使用$expr

db.bcamp.aggregate(
[
  {$match: {$expr: {$eq: ["$budget", "$clickcost"]}}}
]).pretty();

或者
db.bcamp.find(
 {$expr: {$eq: ["$budget", "$clickcost"]}}
).pretty();

当我将值更改为int时,budget会变成NumberLong(),但click_cost会像这样:"click_cost":150。 - Mohammad_Hosseini
你是如何更新这些值的?这些数字默认存储为浮点数。你必须将它们更新为NumberLong("somevalue")以获得长整型值。类似这样的操作:db.collection.update( { user_id: 1 }, { $set: { click_cost: NumberLong("102000") } } )。对于32位值,使用NumberInt。 - s7vr
好的,我已经将它们更改为NumberLong(...),然后运行了您的代码,但是我得到了4个结果对象-其中我的对象预算低于点击成本,有些对象没有预算或点击成本值-这是怎么发生的?没有一个对象的预算与其点击成本相同。 - Mohammad_Hosseini
如果您想要筛选出预算值低于点击成本的行,请将匹配项更改为-1。如果第一个值小于第二个值,则返回-1。如果第一个值大于第二个值,则返回1。如果两个值相等,则返回0。 - s7vr
似乎在聚合查询中有一个错别字 click_cost vs clickcost。 - s7vr
不确定你在问什么。如果它起作用,您可以按照上面的答案使用它。 - s7vr

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