如何在查询中使用 $push 将数据插入子文档,而不是检索文档并将其保存回来

Posted

技术标签:

【中文标题】如何在查询中使用 $push 将数据插入子文档,而不是检索文档并将其保存回来【英文标题】:How to insert data into subdocument using $push in query, instead of retrieving doc and saving it back 【发布时间】:2016-02-04 07:39:29 【问题描述】:

编辑:这确实有效

正如Mongoose - Subdocs: "Adding subdocs" 文档所说,我们可以使用push 方法添加子文档(即parent.children.push( name: 'Liesl' );

但我想更进一步,想使用$push 运算符插入子文档。

我有两个架构:ThingSchema:

var ThingSchema = mongoose.Schema(
  name: 
    type: String,
    required: true
  ,
  description: 
    type: String
  
);

还有BoxSchema,主文档有一组ThingSchema的子文档(things):

var BoxSchema = new mongoose.Schema(
  name: 
    type: String,
    required: true
  ,
  description: 
    type: String
  ,
  things: 
    type: [ThingSchema]
  
);

var BoxModel = mongoose.model('Box', BoxSchema);

我需要things 中的每个子文档 具有unique 名称 - 也就是说,不可能将一个新文档插入到该数组中,该数组的 name 值已经存在于子文档中。

我正在尝试做类似的事情:

var thingObj = ... // the 'thing' object to be inserted

BoxModel.update(
  _id: some_box_id, // a valid 'box' ObjectId
  "things.name":  "$ne": thingObj.name 
,

  $push:  things: thingObj
, 
function(err) 
  if (err) // handle err
  ...
);

但没有得到任何想要的结果。

在查询中使用$push 运算符将ThingSchema 子文档添加到BoxSchemathing 数组中的正确方法是什么(必须不添加subdoc 如果有另一个子文档名称相同),而不是 Mongoose Docs 方式?


编辑:这实际上是问题

我犯了一个错误,上面的代码按预期工作但是现在我遇到的问题是当thingObjThingSchema不匹配时,一个空对象被插入到@987654341 @数组:

// now thingObj is trash
var thingObj =  some: "trash", more: "trash" ;

当执行给定上述垃圾对象的查询时,以下空对象被插入到 subdocs 数组中:

 _id: ObjectId("an_obj_id") 

我想要这种情况,当thingObjThingSchema 不匹配时,无需添加任何内容。

【问题讨论】:

你所拥有的应该在技术上工作我实际上看不出有什么问题......"things.name" : "$ne" : thingObj.name 是正确的。如果您尝试仅通过 things.name === thingObj.name 进行搜索,您会得到结果吗? @MarkPieszak 你是对的,它确实有效!但无论如何,它仍然没有按照我的预期行事。我刚刚编辑了我的问题,指出了剩下的问题。 【参考方案1】:

$addToSet 为数组添加了一些独特的东西(因为它检查重复项)。但它只适用于原语。

你应该做的是把things放到他们自己的集合中,并在名字上做一个唯一的索引。然后,进行此更改

things: 
  type: [type: ObjectId, ref: 'thingscollection']

这样就可以了

BoxModel.update(
  _id: some_box_id, // a valid 'box' ObjectId
  "things":  "$ne": thingObj._id 
,

  $addToSet:  things: thingObj._id
, 
function(err) 
  if (err) // handle err
  ...
);

当您获取时,请使用 things 上的 .populate 获取完整的文档。

这并不完全符合您的要求,但这种设计可能会实现您的目标。

【讨论】:

正如你所说,这不是我想要的。我想知道如何按照我解释的方式进行操作。

以上是关于如何在查询中使用 $push 将数据插入子文档,而不是检索文档并将其保存回来的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Monk 在 MongoDB 中插入带有子文档数组元素的文档

Yii,MongoDB查询子文档以插入Mysql表

如何在插入中使用子查询? [关闭]

mongodb怎么插入多个文档

使用 Node.js 将数组插入 MongoDB 子文档

如何使用 SQL 中的 Case 语句将数据插入临时表