当前位置: 首页 > 知识库问答 >
问题:

在mongoose(updateOne-$pull)不工作的情况下删除MongoDB中数组中的嵌入文档

彭烨烁
2023-03-14

我有一个应用程序与MongoDB(猫鼬)在NodeJs。

在一个集合中,我有这种类型的文档,按周定义:

{
"_id":
{"$oid":"617f3f51f883fab2de3e7260"},
"endDate":{"$date":"2021-11-07T23:59:59.000Z"},
"startDate":{"$date":"2021-11-01T00:00:00.000Z"},
"wastes":[
{"timestamp":{"$date":"2021-11-01T01:00:58.000Z"},"duration":780},
{"timestamp":{"$date":"2021-11-01T01:00:58.000Z"},"duration":1140},
{"timestamp":{"$date":"2021-11-01T03:00:58.000Z"},"duration":540},
{"timestamp":{"$date":"2021-11-01T07:00:58.000Z"},"duration":540},
{"timestamp":{"$date":"2021-11-01T09:00:58.000Z"},"duration":960},
{"timestamp":{"$date":"2021-11-01T09:00:58.000Z"},"duration":1140},
{"timestamp":{"$date":"2021-11-01T15:00:58.000Z"},"duration":180},
{"timestamp":{"$date":"2021-11-01T15:00:58.000Z"},"duration":540}
...
]}

我有一个查找具有相同时间戳的废物的函数,例如“2021-11-01T01:00:58.000Z”,它给出了此时间戳的最长持续时间。

我想删除所有条目与该时间戳:

{"timestamp":{"$date":"2021-11-01T01:00:58.000Z"},"duration":780},
{"timestamp":{"$date":"2021-11-01T01:00:58.000Z"},"duration":1140}

并只插入持续时间最高的一个:

{"timestamp":{"$date":"2021-11-01T01:00:58.000Z"},"duration":1140}

我正在使用带有$pull和$push的updateOne,但它不起作用。

let query = {
        startDate: new Date(startDayWeek),
      };

let deleteProjection = {
        $pull: {
          wastes: { timestamp: new Date(timestampDeleteInsertion) },
        },
      };

let insertProjection = {
        $push: { wastes: insertRegisterForTimestamp },
      };

//Delete
await coleccion.updateOne(query, deleteProjection);

//Insertion
await coleccion.updateOne(query, insertProjection);

我还尝试了{upsert:false},{multi:true}

如果我在MongoDB Compass shell中使用相同的命令,那么它可以正常工作:

//Delete
db.coleccion.updateOne({startDate: ISODate('2021-11-01T00:00:00')}, {$pull: {'wastes': {timestamp: ISODate('2021-11-01T01:00:58.000Z')}}})

//Insertion
db.coleccion.updateOne({startDate: ISODate('2021-11-01T00:00:00')}, {$push: {'wastes': {'timestamp':ISODate('2021-11-01T01:00:58.000Z'), 'duration': 1140}}})

共有1个答案

糜博远
2023-03-14

通过使用聚合管道进行更新,可以实现预期的行为

聚合将包括3个步骤:

  1. 使用$reduce找出最大持续时间;将结果存储到字段中
db.collection.update({},
[
  {
    $addFields: {
      maxDuration: {
        "$reduce": {
          "input": "$wastes",
          "initialValue": null,
          "in": {
            "$cond": {
              "if": {
                $and: [
                  {
                    $eq: [
                      "$$this.timestamp",
                      {
                        "$date": "2021-11-01T01:00:58.000Z"
                      }
                    ]
                  },
                  {
                    $gt: [
                      "$$this.duration",
                      "$$value"
                    ]
                  }
                ]
              },
              "then": "$$this.duration",
              "else": "$$value"
            }
          }
        }
      }
    }
  },
  {
    $set: {
      wastes: {
        $filter: {
          input: "$wastes",
          as: "w",
          cond: {
            $or: [
              {
                $ne: [
                  "$$w.timestamp",
                  {
                    "$date": "2021-11-01T01:00:58.000Z"
                  }
                ]
              },
              {
                $eq: [
                  "$$w.duration",
                  "$maxDuration"
                ]
              }
            ]
          }
        }
      }
    }
  },
  {
    "$unset": "maxDuration"
  }
])

这是蒙哥游乐场供你参考。

 类似资料:
  • 我在MongoDB中有一个收藏,如下所示: 但是,我无法找到一个查询来实现这种效果。基本上,一个tweetID会参与多个簇,因此会出现在各个簇的成员属性的多个子文档中。我想提供一个bulk$pull操作,在这里我可以删除所有集群中的所有子文档(即它们的成员属性),这些子文档与特定的tweetid匹配。 一些帮助和直觉会真的很有帮助。

  • 我正在建立一个应用程序,并使用MariaDB作为我的数据库。我有一张桌子“kick_votes”。其主键包含三个字段: null

  • 我是mongoDB新手,在使用Mongoose从mongoDB中的数组中删除团队对象时遇到困难。我的用户收藏看起来像; 我的移除路线看起来像; 控制台在用户之前和之后记录日志。更新是完全相同的,我没有得到任何错误抛出。控制台的输出。日志(错误、数据)最终被删除 我不知道该怎么解释。我也尝试过不按这里的建议传入userID;https://stackoverflow.com/a/24289161/5

  • 文件: 我想从“数组”项中删除一个项,而不知道文档的_id,只知道元素的id,我有一个查找元素的查询,它在mongodb shell中工作,但在mongoose中不工作, 你知道为什么吗? 你能给我同等的猫鼬吗? 我应该如何从列表中提取该项,而只知道它的_id?

  • 改变原始数组,过滤掉指定的值。 使用 Array.filter() 和 Array.includes() 来剔除指定的值。使用 Array.length = 0 将数组中的长度重置为零,并且通过 Array.push() 只使用 pulled 值重新填充数组。 (对于不改变原始数组的代码片段,请参阅without) const pull = (arr, ...args) => { let ar

  • b)“Units”字段包含带有“period”字段的子文档(日期对象数组),其中给定的日期位于数组中的第一和第二元素之间。 数据结构如下所示: 我尝试使用.find()和.aggregate()的各种组合,例如在periol数组上使用$project和$filter,在unit._id上使用$elemmatch之后使用$elemmatch,但是没有用--我得到了诸如“不能在数组上使用$filter