从项目数组设置增量值

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从项目数组设置增量值相关的知识,希望对你有一定的参考价值。

如何更新MongoDB中的多个文档并按递增顺序设置元素的值?

我的文件如下

{
   "_id" :  ObjectId("5b162a31dfaf342dc44c920d")   
}
{
   "_id" :  ObjectId("5b162a31dfaf342dc44c920f")  
}
{
   "_id" :  ObjectId("5b162a31dfaf342dc44c920c")  
}

如何使用单个查询更新整个文档,以便我可以按递增顺序在每个字段中创建一个名为“order”的新元素,如下所示

{
   "_id" :  ObjectId("5b162a31dfaf342dc44c920d"),
   "order": 1
}
{
   "_id" :  ObjectId("5b162a31dfaf342dc44c920f"),
    "order": 2  
}
{
   "_id" :  ObjectId("5b162a31dfaf342dc44c920c"),
    "order": 3  
}

目前我使用以下方法来解决问题

   for(let i = 0; i <= req.body.id.length;i++) {

            const queryOpts = {
                _id: ObjectId(req.body.id[i])
            };

            const updateOpts = {
                $set: {
                    'order': i + 1
                }
            };

        const dataRes = await req.db.collection('GalleryImage').updateOne(queryOpts, updateOpts); 

         if(i === req.body.id.length-1) {
                return commonHelper.sendResponseMessage(res, dataRes, {
                    _id: req.body.id
                }, moduleConfig.message.updateGalleryOrder);


            }

如果还有比这更好的方法,那么如果有大量的文件,它就不会是昂贵的操作?

答案

使用bulkWrite()Array.map()构造语句:

try {
  let response = await req.db.collection('GalleryImage').bulkWrite(
    req.body.id.map((_id,order) => 
      ({ updateOne: {
       filter: { _id: ObjectId(_id) },
       update: {
         $set: { order: order+1 }
       }
      }})
    )
  );
 } catch(e) {
   // deal with any errors
 }

Array.map()具有在其第二个函数参数内处理的数组元素的“索引”。所以只需使用它来获取order并在所有语句中设置它。

而不是用数据库n写/响应时间,这只需要“一次”发生。

没有其他方法可以获得除了自己引入之外的“序列”,但至少我们可以用“one”这样写,而不是几个。使用async/await语法时还要注意“捕获可能的错误”。


Example listing

const { MongoClient, ObjectID: ObjectId } = require('mongodb');

const uri = 'mongodb://localhost:27017';

const data = [
  "5b162a31dfaf342dc44c920d",
  "5b162a31dfaf342dc44c920f",
  "5b162a31dfaf342dc44c920c"
];

const log = data => console.log(JSON.stringify(data, undefined, 2));
(async function() {

  try {

    const client = await MongoClient.connect(uri);
    let db = client.db('test');

    // Set up
    await db.collection('gallery').removeMany({});
    await db.collection('gallery').insertMany(
      data.map(_id => ({ _id: ObjectId(_id) }))
    );

    // Update with indexes
    let response = await db.collection('gallery').bulkWrite(
      data.map((_id,idx) =>
        ({
          updateOne: {
            filter: { _id: ObjectId(_id) },
            update: { $set: { order: idx+1 } }
          }
        })
      )
    );

    log({ response });

    let items = await db.collection('gallery').find().toArray();
    log({ items });

    client.close();

  } catch(e) {
    console.error(e)
  } finally {
    process.exit()
  }

})()

和输出

{
  "response": {
    "ok": 1,
    "writeErrors": [],
    "writeConcernErrors": [],
    "insertedIds": [],
    "nInserted": 0,
    "nUpserted": 0,
    "nMatched": 3,
    "nModified": 3,
    "nRemoved": 0,
    "upserted": [],
    "lastOp": {
      "ts": "6563535160225038345",
      "t": 18
    }
  }
}
{
  "items": [
    {
      "_id": "5b162a31dfaf342dc44c920d",
      "order": 1
    },
    {
      "_id": "5b162a31dfaf342dc44c920f",
      "order": 2
    },
    {
      "_id": "5b162a31dfaf342dc44c920c",
      "order": 3
    }
  ]
}

清楚地显示nMatched: 3nModified: 3正如预期的那样。

以上是关于从项目数组设置增量值的主要内容,如果未能解决你的问题,请参考以下文章

从活动中更改片段的变量值

javascript for循环,如果增量值不匹配则嵌套?

为啥我的函数向返回未定义的对象数组添加键和增量值

添加自定义自动增量值

MySQL自动增量值设置为零

MySQL Workbench - 更改下一个自动增量值不起作用