【问题标题】:Retrieve Documents where sum of sizes of arrays is greater than given value检索数组大小总和大于给定值的文档
【发布时间】:2017-05-28 09:19:39
【问题描述】:

我有一个这样定义的 Mongoose 架构:

const hackathonSchema = new mongoose.Schema({
    hackathonId: {type: Number, required: true},
    uuid: {type: String, required: true},
    data: {type: Object, required: true},
    isPublished: {type: Boolean, default: false},
    organisers: [String],
    volunteers: [String],
    participants: [String],
    mentors: [String]
});

export default mongoose.model('Hackathon', hackathonSchema);

我想检索所有的黑客马拉松,其中 长度:

( organisers + volunteers + participants +mentors ) >= 500

或任何与此相关的价值。

我找到了一个这样的答案,但不是在 Mongoose How to select where sum of fields is greater than a value in MongoDB

【问题讨论】:

    标签: mongodb mongoose mongodb-query aggregation-framework


    【解决方案1】:

    只需将尺寸相加:

    在 MongoDB 3.4 或更高版本中使用$concatArrays

    Model.aggregate([
      { "$redact": {
        "$cond": {
          "if": {
            "$gt": [
              { "$size": {
                "$concatArrays": [
                  { "$ifNull": [ "$organisers", [] ]  },
                  { "$ifNull": [ "$volunteers", [] ]  },
                  { "$ifNull"; [ "$participants", [] ] },
                  { "$ifNull": [ "$mentors", [] ] }
                ]
              } },
              500
            ]    
          },
          "then": "$$KEEP",
          "else": "$$PRUNE"
        }
      }},
      { "$project": { "_id": 1 } }
    ],function(err,results) { 
    
    })
    

    或者在没有该运算符的早期版本中

    Model.aggregate([
      { "$redact": {
        "$cond": {
          "if": {
            "$gt": [
              { "$add": [
                { "$size": { "$ifNull": [ "$organisers", [] ] } },
                { "$size": { "$ifNull": [ "$volunteers", [] ] } },
                { "$size": { "$ifNull": [ "$participants", [] ] } },
                { "$size": { "$ifNull": [ "$mentors", [] ] } }
              ]},
              500
            ]    
          },
          "then": "$$KEEP",
          "else": "$$PRUNE"
        }
      }},
      { "$project": { "_id": 1 } }
    ],function(err,results) { 
    
    })
    

    在任何一种方法中,您都使用$redact 作为集合中文档的逻辑过滤器。作为本地操作员,这是您处理这种情况的最快方式。

    在内部,它的唯一参数是$cond,这是一个“三元”操作( if/then/else )来评估和返回一个值。因此,当"if" 条件的结果导致true"then" 时,操作是$$KEEP 文档,或者"else"$$PRUNE 结果中的文档。

    基于版本的不同方法是:

    至于只返回_id 字段,那么添加$project 阶段就很简单了,就像在常规查询投影中一样,您提供要返回的属性列表。在这种情况下,只有_id 字段。

    您可以先使用$match 在基本查询中添加一些关于最小数组长度的假设,但这只是一个假设,而不是绝对事实。


    作为记录,您可以使用 $where 子句运行完全相同的东西,但是由于此运算符使用 JavaScript 评估,而不是像聚合框架操作那样本机实现,因此它确实会对性能产生重大影响它运行得更慢:

    Model.find({ "$where": function() {
       return [
         ...this.organisers,
         ...this.volunteers,
         ...this.participants,
         ...this.mentors
       ].length > 500
    }).select({ "_id": 1 }).exec(function(err,results) {
    })
    

    因此,与聚合管道结构的 DSL 形式相比,它可能“看起来很漂亮”,但性能损失并不值得。只有当您的 MongoDB 版本缺少 $redact 作为运算符时,您才应该这样做,这将在 MongoDB 2.6 之前。在这种情况下,您可能还应该出于其他原因更新 MongoDB。

    【讨论】:

    • 'redact' 操作符在这里实现了什么?其余的我都能理解!
    • @bholagabbar 有一个链接。我实际上是在你打字的时候添加解释。
    • 现在,如果我只想检索 Hackathon Id id 的列表而不是整个模型,如何修改此查询?如果是find() 查询,我会这样做find({id}, ...query);这里也一样吗?
    • @bholagabbar 添加。熟悉Aggregation Operators 可能是一个很好的练习。使用 MongoDB,您将需要知道如何使用这些。
    猜你喜欢
    • 2014-08-07
    • 2016-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-10
    相关资源
    最近更新 更多