javascript - MongoDB - 检查 $addToSet 是否重复

标签 javascript node.js mongodb mongodb-query

我正在使用 MongoDB 为我的应用程序创建类似的功能。我最近偶然发现一个问题。

我喜欢的代码:

async function like(articleId, userId) {
const db = await makeDb();
return new Promise((resolve, reject) => {
  const result = db.collection(collectionName).findOneAndUpdate(
    { articleId: ObjectID(articleId) },
    {
      $setOnInsert: {
        articleId: ObjectID(articleId),
        creationDate: new Date()
      },
      $addToSet: { likes: ObjectID(userId) }
    },
    { upsert: true }
  );
  resolve(result);
});

它的作用:

  1. 如果集合中没有文档,请创建一个文档并填写所有字段
  2. 如果文档存在,仅使用新的用户 ID 更新 likes 数组

这按预期工作,没有任何问题,感谢 $addToSet 我没有任何重复项等。

但是,在执行上述代码并返回结果之后,我需要做一些额外的事情,为了让它工作,我需要知道 Mongos $addToSet 是否做了改变任何东西。

简而言之:

  1. 如果新的 userId 已添加到 likes 数组中,我想做点什么
  2. 如果 userId 已在 likes 数组中,并且 $addToSet 没有更改任何内容,我不想采取任何操作。

有没有办法区分$addToSet是否做了什么?

结果的当前 console.log() 如下所示:

  { 
    lastErrorObject: { n: 1, updatedExisting: true },
    value: { _id: 5e2c47c57bb5183d80dce14f,
             articleId: 5da4d1365217baf52fbcd76a,
             creationDate: 2020-01-25T13:51:01.928Z,
             likes: [ 5d750b677d8edfc08af8a527 ] 
    },
    ok: 1 
  }

我想到的一件事(但在性能方面非常糟糕)是在更新之前比较 likes 数组是否包含 userID 与 javascript includes 方法。

还有更好的想法吗?

最佳答案

我找到了解决方案!

这个答案的 99% 归功于 Neil Lunn: https://stackoverflow.com/a/44994382/2175228

它让我走上了正轨。我放弃了 findOneAndUpdate 方法,转而使用 updateOne 方法。查询参数等一切都保持不变,只是方法名称发生了变化,显然该方法的结果类型也发生了变化。

updateOne 方法的问题是它不返回已更新的对象(或旧的对象)。但它确实返回了upsertedId,这是我的情况下唯一需要的。

所以最终你得到的是一个非常长的 CommandResult 对象,其开头为:

 CommandResult {
  result: { n: 1, nModified: 0, ok: 1 },
  (...)
 }

但是当我仔细观察时,我注意到该对象恰好具有我一直需要的那些字段:

  modifiedCount: 0,
  upsertedId: null, // if object was inserted, this field will contain it's ID
  upsertedCount: 0,
  matchedCount: 1 

所以您需要做的就是从 CommandResult 对象中获取您需要的部分,然后继续;)

更改后我的代码:

async function like(articleId, userId) {
    const db = await makeDb();
    return new Promise((resolve, reject) => {
      db.collection(collectionName)
        .updateOne(
          { articleId: ObjectID(articleId) },
          {
            $setOnInsert: {
              articleId: ObjectID(articleId),
              creationDate: new Date()
            },
            $addToSet: { likes: ObjectID(userId) }
          },
          { upsert: true }
        )
        .then(data => {
          // wrap the content that You need
          const result = {
            upsertedId: data.upsertedId,
            upsertedCount: data.upsertedCount,
            modifiedCount: data.modifiedCount
          };

          resolve(result);
        });
    });
  }

希望这个答案能够帮助将来遇到类似问题的人:)

关于javascript - MongoDB - 检查 $addToSet 是否重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59910077/

相关文章:

javascript - 如何一次只展开一个 Accordion 选项卡?

node.js - 如何在 keycloak 中验证 token 并获取用户详细信息?

node.js - 在 Node.js 中使用 Promise 会使 Node 同步吗?

javascript - Mongoose 查询 "hot"帖子

java - 如何使用存储库接口(interface)在 Spring Data 中通过其嵌套对象的 objectId 查找集合?

javascript - Javascript 中用于检查@符号的正则表达式

javascript - 将复选框更改为开关样式按钮

java - 在 Springdata MongoDB 中查询 mongoDB 按数组值排序并使用分页

Javascript 打包问题

javascript - 如何测试 REST API + 客户端 MVC 应用程序?