【问题标题】:What is the correct syntax for $set of an array element of an embedded doc?嵌入式文档的数组元素的 $set 的正确语法是什么?
【发布时间】:2014-09-25 20:06:16
【问题描述】:

目前,由于语法错误,Mongo 正在跳过此更新。当我为 $.to 尝试不同的展示位置时。 (如replies.$.to),结果:[MongoError: cannot use the part (to of replies.0.to.read.marked) to traverse the element..]

$set应该如何编辑:

Models.Message.findOneAndUpdate(

  { "replies._id": ObjectId("53dd4b67f0f23cad267f9d8b"), "replies.to.username": "UserA" },
  {
    "$set": { 
        "$.to.read.marked": true,
        "$.to.read.datetime": req.body.datetimeRead,
        "$.to.updated": req.body.datetimeRead
    }
  },

to $set to.read.marked:true for userA 的具体回复:

{
    "_id" : ObjectId("53daf26af7b70fd82ffd4cff"),
    "updated" : ISODate("2014-08-02T20:36:03.000Z"),
    "message" : "here's a message",
    "replies" : [ 
        {
            "reply" : "here's a reply",
            "created" : 1407011687000,
            "_id" : ObjectId("53dd4b67f0f23cad267f9d8b"),
            "to" : [ 
                {
                    "username" : "userA",
                    "updated" : ISODate("2014-08-02T20:34:47.000Z"),
                    "_id" : ObjectId("53dd4b67f0f23cad267f9d8c"),
                    "read" : {
                        "datetime" : ISODate("2014-08-02T20:34:47.000Z"),
                        "marked" : false
                    }
                },
                {
                    "username" : "userB",
                    "updated" : ISODate("2014-08-02T20:34:47.000Z"),
                    "_id" : ObjectId("53dd4b67f0f23cad267f9d8d"),
                    "read" : {
                        "datetime" : ISODate("2014-08-02T20:34:47.000Z"),
                        "marked" : false
                    }
                }
            ]
        }, 
        {
            "reply" : "here's another reply",
            "created" : 1407011763000,
            "_id" : ObjectId("53dd4bb3a9f9497e270525cb"),
            "to" : [ 
                {
                    "username" : "userA",
                    "updated" : ISODate("2014-08-02T20:36:03.000Z"),
                    "_id" : ObjectId("53dd4bb3a9f9497e270525cc"),
                    "read" : {
                        "datetime" : ISODate("2014-08-02T20:36:03.000Z"),
                        "marked" : false
                    }
                },
                {
                    "username" : "userB",
                    "updated" : ISODate("2014-08-02T20:36:03.000Z"),
                    "_id" : ObjectId("53dd4bb3a9f9497e270525cd"),
                    "read" : {
                        "datetime" : ISODate("2014-08-02T20:36:03.000Z"),
                        "marked" : false
                    }
                }
            ]
        }
    ],
    ...
}

【问题讨论】:

    标签: mongodb mongoose


    【解决方案1】:

    您不能将$ 用于嵌套数组。所以你根本不能使用update。 关注this issue

    因此,您需要对replies._id 进行find 查询并继续手动获取索引/索引。

    一个丑陋的选择是

    Models.Message.findOne({ "replies._id":ObjectId("53dd4b67f0f23cad267f9d8b", "replies.to.username": "UserA")},
       function(err,doc){
           if(doc){
           //use a for loop over doc.replies to find the index(index1) of ObjectId("53dd4b67f0f23cad267f9d8b") at replies[index]._id
           var index1;
           for(var i=0;i<doc.replies.length;i++){
              if(doc.replies[i]._id === ObjectId("53dd4b67f0f23cad267f9d8b")){
                 index1=i;
                 break;
              }
            }
            var index2;
           //use a for loop over doc.replies[index1].to and find the index(index2) of "UserA" at replies[index1].to[index2]
           for(var j=0;j<doc.replies[index1].to.length;j++){
             if(doc.replies[index1].to[index2].username==="UserA"){
                index2=j;
                break;
             }
           } 
    
           doc.replies[index1].to[index2].read.marked = true;
           doc.replies[index1].to[index2].read.datetime = req.body.datetimeRead;
           doc.replies[index1].to[index2].updated= req.body.datetimeRead;
           doc.markModified('replies')
           doc.save(function(err,doc2){...})
         }
       });
    

    【讨论】:

    • 哇。好的..谢谢你的提醒。有没有其他方法可以产生预期的结果?
    • 如果我传递replies.to._id 而不是replies._id 可以更新吗?
    • 还是没有。同样的问题适用 - 嵌套数组。该更新也需要多个不存在的位置运算符。如果您经常需要此类嵌套更新,请考虑重新设计您的架构。理论上是可行的,但会涉及很多开销。
    • Hmm.. 如果用 if (something) {repliesIDsArray.forEach(repliesIDsArrayUpdate); 封装,您所说的 find 查询会是伪同步的吗? ..find 查询每个回复._id.. } 这样代码将在此之后继续执行 if & forEach 完成了吗? (node.js)
    • 这是一个频繁的操作..对于替代架构设计有什么建议吗?
    猜你喜欢
    • 1970-01-01
    • 2016-01-14
    • 2022-11-25
    • 1970-01-01
    • 2011-06-11
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 2017-07-08
    相关资源
    最近更新 更多