【问题标题】:MongoDB remove elements depending on element before (Iterating)MongoDB 根据之前的元素删除元素(迭代)
【发布时间】:2020-12-08 09:47:49
【问题描述】:

如果同一个对象具有相似的元素,我想从我的 MongoDB 对象中删除 ($unset) 元素。 我的对象:

{
   "_id": "5eabf8b144345b36b00bfbaa",
   "ranktime": [{
      "pos":"2",
      "datum":"Mon May 05 2020 12:22:52 GMT+0200 (GMT+02:00)",
      "source":"SOURCE2"
    },{
      "pos":"1",
      "datum":"Fri May 01 2020 12:23:10 GMT+0200 (GMT+02:00)",
      "source":"SOURCE1"
    },{
      "pos":"37",
      "datum":"Fri May 01 2020 12:25:14 GMT+0200 (GMT+02:00)",
      "source":"SOURCE2"
    },{
      "pos":"12",
      "datum":"Fri May 01 2020 12:25:14 GMT+0200 (GMT+02:00)",
      "source":"SOURCE2"
    },{
      "pos":"37",
      "datum":"Fri May 01 2020 18:45:27 GMT+0200 (GMT+02:00)",
      "source":"SOURCE2"
    }]
}

所以如果ranktime.source == "SOURCE2" 并且日期与之前的对象相同,我想删除ranktime 中的条目。实际上我必须遍历ranktime 的单个元素。这在 MongoDB 中可行吗?

预期结果是:

{
   "_id": "5eabf8b144345b36b00bfbaa",
   "ranktime": [{
      "pos":"2",
      "datum":"Mon May 05 2020 12:22:52 GMT+0200 (GMT+02:00)",
      "source":"SOURCE2"
    },{
      "pos":"1",
      "datum":"Fri May 01 2020 12:23:10 GMT+0200 (GMT+02:00)",
      "source":"SOURCE1"
    },{
      "pos":"37",
      "datum":"Fri May 01 2020 12:25:14 GMT+0200 (GMT+02:00)",
      "source":"SOURCE2"
    }]
}

【问题讨论】:

  • 您的 MongoDB 版本是多少?以及为什么最后一个被删除(唯一日期)
  • 我的版本是 4.2.8,抱歉,我的意思是同一日期(天),忽略时间。这就是为什么最后一个被删除

标签: arrays mongodb mongoose mongodb-query


【解决方案1】:

基本上,您可以使用$reduce 处理数组并使用$let$arrayElemAt 语句定义前一个元素。新的$set 语法允许您在更新语句中使用聚合:

db.col.updateMany({}, [
    {
        $set: {
            ranktime: {
                $reduce: {
                    input: "$ranktime",
                    initialValue: [],
                    in: {
                        $let: {
                            vars: { last: { $arrayElemAt: [ "$$value", -1 ] } },
                            in: {
                                $cond: [ 
                                    { 
                                        $and: [ 
                                            { "$eq": [ "$$last.source", "SOURCE2" ] },
                                            { "$eq": [ { $substr: [ "$$last.datum", 0, 15 ] }, { $substr: [ "$$this.datum", 0, 15 ] } ] },
                                        ]
                                    },
                                    "$$value",
                                    { $concatArrays: [ "$$value", [ "$$this" ] ] }
                                ]
                            }
                        }
                    }
                }
            }
        }
    }
])

Aggregation Example

【讨论】:

  • 非常感谢!这太棒了。我只是有另一个问题。是否不仅要考虑最后一个元素,还要考虑数组中的所有元素?可能会发生相同的对象不会一个接一个地存储。你对这个案子有什么建议吗?谢谢!
  • @AlexanderRiedel 您仍然可以使用相同的方法并引用包含所有先前值的 $$value$ranktime 引用所有值
  • 好的,据我所知,我必须放弃$arrayElemAt: [ "$$value", -1 ] ,我必须提供整个数组。但是设置vars: { last: "$ranktime } 不起作用。是否有关于 MongoDB 中的 $$value 变量的任何文档?它没有在$let 语句中定义,但$let 的文档说您只能使用已定义的变量,而且它似乎也不是系统变量?谢谢!
  • $$value 是 $reduce 之前迭代的结果,所以它最初是一个空数组,然后它包含 $concatArrays 的乘积
  • 好的,所以参考$ranktime(它包含所有值)而不是只有$$value 应该可以工作,但我不知何故错过了什么? mongoplayground.net/p/xzOFbfz3Zsa 更改在第 13 行
猜你喜欢
  • 2020-12-11
  • 1970-01-01
  • 2011-03-09
  • 2011-06-25
  • 2013-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-18
相关资源
最近更新 更多