【问题标题】:Are there computed fields in MongoDB? [duplicate]MongoDB中有计算字段吗? [复制]
【发布时间】:2016-05-26 06:38:08
【问题描述】:

MongoDB中有计算字段吗?

在 SQL 中我可以做到:

SELECT A+B AS C FROM MYTABLE WHERE C>10

我可以在 MongoDB 中做类似的事情吗?

更新

我做了投影:

db.segments.aggregate(
   [
      {
         $project: {
            "_id": 1,
            numberOfRestrictions: { $size: "$Speed Restrictions" }
         }
      }
   ]
)

它有效。

不幸的是,进一步的流水线不会:

db.segments.aggregate(
   [
      {
         $project: {
            "_id": 1,
            numberOfRestrictions: { $size: "$Speed Restrictions" }
         }
      },
      {
        $match: {
            "numberOfRestrictions": {
                "$gt": 1
            }
        }
      }
   ]
)

后者导致错误

The argument to $size must be an Array, but was of type: EOO

【问题讨论】:

  • 你能展示一些示例文档和预期的输出吗?
  • 第一次单独查询后,文档看起来像{ "_id" : ObjectId("12345"), "numberOfRestrictions" : 1 }
  • 我的意思是 segments 集合中的一些示例文档以及您对这些示例文档所期望的最终结果。

标签: mongodb nosql


【解决方案1】:

有一个名为 $expr 的运算符使您能够在 find() 查询中使用聚合框架运算符。

例如,SQL 查询

SELECT A+B AS C FROM MYTABLE WHERE C>10

可以翻译成mongo查询

db.segments.find({ 
    "$expr": {
        "$gt": [
            { "$add": [ "$A", "$B" ] },
            10
        ]
    }
})

对于检查数组长度也是类似的

db.segments.find({ 
    "$expr": {
        "$gt": [
            { "$size": "$SpeedRestrictions" },
            10
        ]
    }
})

借助聚合框架,还可以在 $match 管道步骤中使用 $expr

db.segments.aggregate([
    { "$match": { 
        "$expr": {
            { "$gt": [
                { "$size": "$SpeedRestrictions" },
                10
            ] }
        }
    } }
])

如果 $expr 运算符不可用,为了向后兼容,可以使用 $redact 作为

db.segments.aggregate([
    { "$redact": { 
        "$cond": [
            { "$gt": [
                { "$size": "$SpeedRestrictions" },
                10
            ] },
            "$$KEEP",
            "$$PRUNE"
        ]
    } }
])

另一种方法是使用 $addFields 管道运算符创建计算字段,并使用 $match 运算符根据该计算字段过滤文档:

db.collection.aggregate([
    { "$addFields": { "C": { "$add": [ "$A", "$B" ] } } },
    { "$match": { "C": { "$gt": 10 } } }
])

【讨论】:

    【解决方案2】:

    是的。它被称为aggregation pipelines。具体来说,需要使用$project阶段创建C字段,然后使用$match阶段查找所有符合条件的文档。

    示例

    让我们先创建一些文档:

    for( var i = 1; i <=10; i++){
      db.agg.insert({a:i,b:i})
    }
    

    这样的集合看起来像这样:

    > db.agg.find()
    { "_id" : ObjectId("56c1b5561a3b578f37a99d4d"), "a" : 1, "b" : 1 }
    { "_id" : ObjectId("56c1b5561a3b578f37a99d4e"), "a" : 2, "b" : 2 }
    { "_id" : ObjectId("56c1b5561a3b578f37a99d4f"), "a" : 3, "b" : 3 }
    { "_id" : ObjectId("56c1b5561a3b578f37a99d50"), "a" : 4, "b" : 4 }
    { "_id" : ObjectId("56c1b5561a3b578f37a99d51"), "a" : 5, "b" : 5 }
    { "_id" : ObjectId("56c1b5561a3b578f37a99d52"), "a" : 6, "b" : 6 }
    { "_id" : ObjectId("56c1b5561a3b578f37a99d53"), "a" : 7, "b" : 7 }
    { "_id" : ObjectId("56c1b5561a3b578f37a99d54"), "a" : 8, "b" : 8 }
    { "_id" : ObjectId("56c1b5561a3b578f37a99d55"), "a" : 9, "b" : 9 }
    { "_id" : ObjectId("56c1b5561a3b578f37a99d56"), "a" : 10, "b" : 10 }
    

    查找所有 C > 10 的文档

    db.agg.aggregate([
        // You need to include all fields you want to have
        // in the resulting document within the $project stage
        { "$project":{ a:1, b:1, c:{ "$add": ["$a","$b"] }}},
        { "$match":{ c:{ "$gt":10 }}}
    ])
    

    返回以下结果:

    { "_id" : ObjectId("56c1b5561a3b578f37a99d52"), "a" : 6, "b" : 6, "c" : 12 }
    { "_id" : ObjectId("56c1b5561a3b578f37a99d53"), "a" : 7, "b" : 7, "c" : 14 }
    { "_id" : ObjectId("56c1b5561a3b578f37a99d54"), "a" : 8, "b" : 8, "c" : 16 }
    { "_id" : ObjectId("56c1b5561a3b578f37a99d55"), "a" : 9, "b" : 9, "c" : 18 }
    { "_id" : ObjectId("56c1b5561a3b578f37a99d56"), "a" : 10, "b" : 10, "c" : 20 }
    

    【讨论】:

    • 但计算字段是否会随着比赛中数据的变化而保持更新?
    猜你喜欢
    • 2018-06-20
    • 1970-01-01
    • 2014-10-15
    • 2021-05-23
    • 1970-01-01
    • 1970-01-01
    • 2013-05-30
    • 2019-04-06
    相关资源
    最近更新 更多