如何使用Mongoose和MongoDB 2.6插入子文档中数组中的特定位置

Posted

技术标签:

【中文标题】如何使用Mongoose和MongoDB 2.6插入子文档中数组中的特定位置【英文标题】:How to insert to the certain position in the array in the subdocument by using Mongoose an MongoDB 2.6 【发布时间】:2014-05-29 18:25:17 【问题描述】:

在我的问题的answer 中给出了如何通过使用 Mongoose 来使用 Mongodb 2.6 的新 $position 运算符的一个很好的解释。建议的解决方案非常适合简单的数组。如果数组在子文档中或数组的每个元素都是数组,则建议的解决方案不起作用。我的意思是这样的:

List.collection.update(
/*....*/,
 "$push": 
    "subdocument.list": 
      "$each": [ 1, 2, 3 ],
      "$position": 0 
    
,function(err,NumAffected) 
  console.log("done");

);
List.collection.update(
/*....*/,
 "$push": 
    "list1.$.list2": 
      "$each": [ 1, 2, 3 ],
      "$position": 0 
    
,function(err,NumAffected) 
  console.log("done");

);

【问题讨论】:

【参考方案1】:

在当前的 Mongoose 版本(4.4.2)中,您可以像这样使用position

Foo.update(query.id,
    
        $push: 
            arrayData: 
                $each: [                       
                    date: new Date
                ], $position: 0 
            
        
    );

【讨论】:

【参考方案2】:

不知道问题出在哪里:

db.list.insert( "list":  "sub": [4]  )
db.list.update(
    ,
     "$push":  "list.sub":  "$each": [1,2,3], "$position": 0   
)

 "list" :  "sub" : [ 1, 2, 3, 4 ]  

这样就可以按预期工作了。

另外一个例子:

db.list.insert(
    outer: [
       
           key: "a", 
           inner: [4]
       ,
       
           key: "b", 
           inner: [4]
       
   ]
)

db.list.update(
     "outer.key": "b" ,
     "$push":  
        "outer.$.inner":  
            "$each": [1,2,3], "$position": 0 
        
    
)

又如预期:


    "outer" : [
            
                    "key" : "a",
                    "inner" : [
                            4
                    ]
            ,
            
                    "key" : "b",
                    "inner" : [
                            1,
                            2,
                            3,
                            4
                    ]
            
    ]

已经解释了与特定驱动程序的交互,因此数据中肯定有一些不同之处,但如果是这样,那么这些陈述是无效的。

所以使用 Mongoose 也是一样的:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost/nodetest');

var listSchema = new Schema(

);

var List = mongoose.model( "List", listSchema );
var Other = mongoose.model( "Other", listSchema );

  List.collection.update(
    ,
     "$push": 
    "list.sub": 
      "$each": [ 1, 2, 3 ],
      "$position": 0 
    
    ,function(err,NumAffected) 
      console.log("done");

    
  );


  Other.collection.update(
     "outer.key": "b" ,
     "$push": 
        "outer.$.inner": 
            "$each": [ 1, 2, 3 ],
            "$position": 0
        
    ,function(err,NumAffected) 
      console.log("done2")
    
  );

【讨论】:

@Roman 您显然没有理解上一个问题的答案。为什么不呢?一旦您绕过驱动程序以外的任何其他交互,那么就没有理由让它起作用。我真的不明白你为什么不能自己尝试。 @Roman 访问 .collection 可以让您绕过 mongoose 并使用底层的 Mongo 驱动程序,因此从某种意义上说,它与 Mongoose 一起“工作”,但它也绕过了 Mongoose 的功能。 @Roman 你用的是什么版本的 Mongodb?在 2.6.x 中引入了position。如果您使用的是 2.4.x,则它不可用。【参考方案3】:

我在 MongooseJS Model.update 中找到了省略对 $position 修饰符的支持的代码。

在 3.8.8 版本中,query.js 的第 1928-1941 行:

      if ('$each' in val) 
        obj[key] = 
            $each: this._castUpdateVal(schema, val.$each, op)
        

        if (val.$slice) 
          obj[key].$slice = val.$slice | 0;
        

        if (val.$sort) 
          obj[key].$sort = val.$sort;
        

      

这里,obj[key] 将被设置为 val.$each。您可以看到对设置 $slice 和 $sort 修饰符的明确支持,但 $position 修饰符永远不会被复制到 obj[key] 中。

所以,虽然你可以绕过 MongooseJS 的 Model.update 函数直接访问 MongoDB 的 update 函数,但显然 MongooseJS 的 Model.update 函数不支持 $position 修饰符。

【讨论】:

MongooseJS 3.9 将支持 $position 修饰符:github.com/LearnBoost/mongoose/issues/2024

以上是关于如何使用Mongoose和MongoDB 2.6插入子文档中数组中的特定位置的主要内容,如果未能解决你的问题,请参考以下文章

我无法使用 Mongoose 在 MongoDB 中保存或查找文档

如何使用用户名和密码连接 mongodb(mongoose)?

如何在不创建 Mongoose 模型的情况下将 GraphQL 与 Mongoose 和 MongoDB 一起使用

如何使用 mongoose ORM 存储/检索到 mongodb

如何使用 Mongoose 使用 MongoDB 事务?

GraphQL、Relay 和 Mongodb (mongoose) 如何获取数组