Javascript Mongoose:在嵌套数组中查找和更新
所以,我有这个模式 购买模式:Javascript Mongoose:在嵌套数组中查找和更新,javascript,arrays,node.js,mongoose,Javascript,Arrays,Node.js,Mongoose,所以,我有这个模式 购买模式: const purchasesSchema = new Schema({ date: String, status: String, product: { type: Schema.Types.ObjectId, ref: 'Product' } }) 产品架构: const productSchema = new Schema({ product_name: String, transaction: [{ price: Number
const purchasesSchema = new Schema({
date: String,
status: String,
product: { type: Schema.Types.ObjectId, ref: 'Product' }
})
产品架构:
const productSchema = new Schema({
product_name: String,
transaction: [{
price: Number,
purchase: { type: Schema.Types.ObjectId, ref: 'Purchases' }
}]
该算法在进行购买之前必须创建产品名称,然后使用bond transaction.purchase在purchase中创建产品交易
采购文件样本:
[{
"_id": "5ac0b7cab7924a1710398c9e",
"date": "01/04/2018",
"status": "Not Paid",
"product": {
"_id": "5ac0b7b1b7924a1710398c9a",
"product_name": "Milk",
"transactions": [
{
"_id": "5ac0b7c9b7924a1710398c9b",
"price": 5000,
}
],
}
}]
交易记录中具有采购id绑定的预期文档
[{
"_id": "5ac0b7cab7924a1710398c9e",
"date": "01/04/2018",
"status": "Not Paid",
"product": {
"_id": "5ac0b7b1b7924a1710398c9a",
"product_name": "Milk",
"transactions": [
{
"_id": "5ac0b7c9b7924a1710398c9b",
"price": 5000,
"purchase": "the id"
}
],
}
}]
到目前为止,我已经尝试过,以防我想将事务推送到已经存在的产品名称:
const newTransaction = {
product_price: req.body.product_price
}
Product.findOneAndUpdate({ _id: req.body.product_id }, { $push: { transaction: newTransaction } }, { new: true }, (err, data) => {
const TRANSACTION_ID = data.transaction[data.transaction.length -1]._id
const newPurchase = new Purchase({
date: moment(req.body.date).format('DD/MM/YYYY'),
status: 'Not Paid',
product: req.body.product_id,
})
newPurchase.save((err, data) => {
if (err) throw err
const PURCHASES_ID = data._id
Product.findOneAndUpdate({ 'transactions._id': TRANSCATION_ID }, { $set: { transactions: { purchase: PURCHASES_ID } } }, (err, data) => { if (err) return handleError(err) })
如何在嵌套数组产品架构中将采购id推送为“transactions.Purchase”的问题。谢谢。根据此答案解决
一般范围和解释
你在这里做的事情有一些问题。首先是查询条件。您引用了几个不需要引用的\u id
值,其中至少有一个不在顶层
为了进入“嵌套”值,并假定\u id
值是唯一的,不会出现在任何其他文档中,您的查询表单应如下所示:
Model.update(
{“array1.array2._id”:“123”},
{“$push”:{“array1.0.array2.$。回答者:“$success”},
功能(错误,未受影响){
//结果在这里
}
);
现在,这确实会起作用,但实际上这只是一个侥幸,因为有很好的理由说明它不应该对你起作用
操作员的官方文档中有“嵌套数组”主题下的重要内容。这说明:
位置$operator不能用于遍历多个数组的查询,例如遍历嵌套在其他数组中的数组的查询,因为$placeholder的替换项是单个值
具体来说,这意味着将在位置占位符中匹配并返回的元素是第一个匹配数组中的索引值。这意味着在您的例子中,匹配索引位于“顶级”数组上
因此,如果您查看如图所示的查询符号,我们已经“硬编码”了顶级数组中的第一个(或0索引)位置,“array2”中的匹配元素也是零索引项
为了演示这一点,您可以将匹配的\u id
值更改为“124”,结果将$push
一个新条目到\u id
为“123”的元素上,因为它们都在“array1”的零索引条目中,并且这是返回到占位符的值
这就是嵌套数组的一般问题。您可以删除其中一个级别,并且仍然能够将$push
推送到“top”数组中的正确元素,但是仍然会有多个级别
尽量避免嵌套数组,因为您将遇到更新问题,如图所示
一般情况下是“展平”你“认为”是“层次”的东西,并在最后的细节项目上实际制作这些“属性”。例如,问题中结构的“扁平”形式应类似于:
{
“答案”:[
{“by”:“success”,“type2”:“123”,“type1”:“12”}
]
}
甚至在接受内部数组时,仅为$push
,且从未更新:
{
“数组”:[
{“类型1”:“12”,“类型2”:“123”,“应答者”:[“成功”]},
{“类型1”:“12”,“类型2”:“124”,“答复者”:[]}
]
}
这两者都有助于在
MongoDB 3.6及以上版本 MongoDB 3.6中有一些新功能可用于嵌套数组。这使用语法来匹配特定元素,并通过update语句中的
arrayFilters
应用不同的条件:
Model.update(
{
“_id”:1,
“阵列1”:{
“$elemMatch”:{
_id:“12”,“array2._id:“123”
}
}
},
{
“$push”:{“array1.$[outer].array2.$[inner].answeredBy:“success”}
},
{
“arrayFilters”:[{“outer.\u id”:“12”},{“inner.\u id”:“123”}]
}
)
传递给或甚至的选项的“arrayFilters”
或方法指定要与update语句中给定的标识符匹配的条件。与给定条件匹配的任何元素都将被更新
由于结构是“嵌套的”,我们实际上使用了“多个过滤器”,如图所示的过滤器定义的“数组”所指定的那样。标记的“标识符”用于与语句的更新块中实际使用的语法进行匹配。在这种情况下,内部
和外部
是用于嵌套链指定的每个条件的标识符
这一新的扩展使嵌套数组内容的更新成为可能,但它实际上无助于“查询”此类数据的实用性,因此前面解释的警告同样适用
你通常真正的“意思”是用“属性”来表达,即使你的大脑最初认为“嵌套”,它通常只是对你认为“以前的关系部分”是如何结合在一起的一种反应。实际上,您确实需要更多的非规范化
另请参见,因为这些新的更新操作符实际上匹配并更新“多个数组元素”,而不仅仅是先前位置更新的第一个
注意具有讽刺意味的是,由于这是在.update()
等方法的“options”参数中指定的,因此语法通常与所有最新版本的驱动程序版本兼容
但是,对于mongo
shell来说,情况并非如此,因为该方法在那里的实现方式(“具有讽刺意味的是,对于向后兼容性”),内部方法不会识别并删除arrayFilters
参数,该方法会解析选项以提供“向后兼容性”使用以前的MongoDB服务器版本和“旧版”.update()
AP