gpt4 book ai didi

node.js - 如何从对象数组中拉出一定范围的对象并将它们重新插入到数组中的新位置?

转载 作者:行者123 更新时间:2023-12-05 07:03:54 24 4
gpt4 key购买 nike

期望的行为

从一个对象数组中拉出一系列对象,并将它们到新索引处的数组。

例如,从索引在0到2之间的数组中拉出对象,并将它们推回数组中的位置6。

作为引用,在 jQuery 中,可以通过以下方式实现所需的行为:

if (before_or_after === "before") {
$("li").eq(new_position).before($("li").slice(range_start, range_end + 1));
} else if (before_or_after === "after") {
$("li").eq(new_position).after($("li").slice(range_start, range_end + 1));
}

jsFiddle demonstration

架构

{
"_id": ObjectId("*********"),
"title": "title text",
"description": "description text",
"statements": [
{
"text": "string",
"id": "********"
},
{
"text": "string",
"id": "********"
},
{
"text": "string",
"id": "********"
},
{
"text": "string",
"id": "********"
},
{
"text": "string",
"id": "********"
}]
}

我尝试过的

我可以使用以下代码在对象数组中重新定位单个对象。

它使用pull 将对象从数组中移除,然后使用push 将其添加回数组的新位置。

为了对对象范围做同样的事情,我想我只需要修改$pull$push变量但是:

  • 我也不知道如何在这种情况下使用 $slice as a projectionan aggregation , 在 $pull 操作中
  • 因为我无法弄清楚第一位,所以我不知道如何尝试第二位 - $push 操作
// define the topic_id to search for  
var topic_id = request_body.topic_id;

// make it usable as a search query
var o_id = new ObjectID(topic_id);

// define the statement_id to search for
var statement_id = request_body.statement_id;

// define new position
var new_position = Number(request_body.new_position);

// define old position
var old_position = Number(request_body.old_position);

// define before or after (this will be relevant later)
// var before_or_after = request_body.before_or_after;

// define the filter
var filter = { _id: o_id };

// define the pull update - to remove the object from the array of objects
var pull_update = {
$pull: {
statements: { id: statement_id } // <----- how do i pull a range of objects here
}
};

// define the projection so that only the 'statements' array is returned
var options = { projection: { statements: 1 } };

try {
// perform the pull update
var topic = await collection.findOneAndUpdate(filter, pull_update, options);

// get the returned statement object so that it can be inserted at the desired index
var returned_statement = topic.value.statements[old_position];

// define the push update - to add the object back to the array at the desired position
var push_update = {
$push: {
statements: {
$each: [returned_statement],
$position: new_position
}
} // <----- how do i push the range of objects back into the array here
};

// perform the push update
var topic = await collection.findOneAndUpdate(filter, push_update);

}

环境

##### local

$ mongod --version
db version v4.0.3

$ npm view mongodb version
3.5.9

$ node -v
v10.16.3

$ systeminfo
OS Name: Microsoft Windows 10 Home
OS Version: 10.0.18363 N/A Build 18363

##### production

$ mongod --version
db version v3.6.3

$ npm view mongodb version
3.5.9

$ node -v
v8.11.4

RedHat OpenShift Online, Linux

编辑

逐渐地,找出问题的一部分,我认为:

使用 the example here ,以下返回数组中索引为 0 - 2 的对象(即 3 个对象):

db.topics.aggregate([
{ "$match": { "_id": ObjectId("********") } },
{ "$project": { "statements": { "$slice": ["$statements", 0, 3] }, _id: 0 } }
])

还不确定如何在 pull 中使用它...

我还调查了 using $in (尽管我宁愿只获取对象的 范围 而不是必须指定每个对象的 ID),但我意识到它不会保留返回结果中提供的数组值的顺序:

Does MongoDB's $in clause guarantee order

这是一种在 Node 中从 $in 重新排序结果的解决方案:

https://stackoverflow.com/a/34751295

最佳答案

这里是 mongo 3.5 的例子

const mongo = require('mongodb')

;(async function (params) {
const client = await mongo.connect('mongodb://localhost:27017')

const coll = client.db('test').collection('test')

const from0to99 = Array(100).fill('0').map((_, i) => String(i))
const from5To28 = Array(24).fill('0').map((_, i) => String(i + 5))

const insert = { statements: from0to99.map(_ => ({ id: _ })) }
await coll.insertOne(insert)

const all100ElementsRead = await coll.findOneAndUpdate(
{ _id: insert._id },
{
$pull: {
statements: {
id: { $in: from5To28 }
}
}
},
{ returnOriginal: true }
)
/**
* It shows the object with the desired _id BEFORE doing the $pull
* You can process all the old elements as you wish
*/
console.log(all100ElementsRead.value.statements)

// I use the object read from the database to push back
// since I know the $in condition, I must filter the array returned
const pushBack = all100ElementsRead.value.statements.filter(_ => from5To28.includes(_.id))

// push back the 5-28 range at position 72
const pushed = await coll.findOneAndUpdate(
{ _id: insert._id },
{
$push: {
statements: {
$each: pushBack,
$position: 72 // 0-indexed
}
}
},
{ returnOriginal: false }
)
console.log(pushed.value.statements) // show all the 100 elements

client.close()
})()

This old issue有帮助

关于node.js - 如何从对象数组中拉出一定范围的对象并将它们重新插入到数组中的新位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63086106/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com