【问题标题】:Adding an array field to a collection based on values of another array field in mongodb根据 mongodb 中另一个数组字段的值将数组字段添加到集合中
【发布时间】:2015-04-23 17:12:21
【问题描述】:

我有一个集合,其结构如下,由一个文档表示

{
_id : 1,
array1 : [{fld1 : 'doc1e1fld1', fld2: 'doc1e1fld2'},{fld1:'doc1e2fld1',fld2: 'doc1e2fld2'}]
}

我想为集合中的所有元素添加另一个字段并设置值,使上面修改后的文档看起来像:

{
    _id : 1,
    array1 : [{fld1 : 'doc1e1fld1', fld2: 'doc1e1fld2'},{fld1:'doc1e2fld1',fld2: 'doc1e2fld2'}],
    array2 : ['doc1e1fld1','doc1e2fld1']
    }

基本上向集合中的所有文档添加一个新的数组元素,并将其内容设置为一个数组,该数组是该文档的array1 中所有元素的fld1 值。

我查看了Update MongoDB field using value of another field,但不知何故我不明白如何提取某些元素。

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    因此,您应该从您引用的问题中意识到,在没有实际查找文档并循环结果以生成更新的情况下,当更新另一个字段时,您实际上无法引用文档中的另一个值。

    因此,底线是您将真正在代码中执行此操作,读取每个文档并从中提取新值以形成新数组。可以使用$set 创建新数组,或者在更新中使用$push$each 运算符可能更安全。

    理想情况下,您也可以使用Bulk Operations API 来获得最佳更新形式。

    最后你也可以将一些数组构造工作委托给aggregation framework,而不是在客户端代码中全部处理,但是更新仍然需要对结果进行:

    var bulk = db.collection.initializeOrderedBulkOp();
    var count = 0;
    
    var cursor = db.collection.aggregate([
        { "$project": {
            "array2": {
                "$map": {
                    "input": "array1",
                    "as": "el",
                    "in": "$$el.fld1"
                }
            }
        }}
    ]);
    
    cursor.forEach(function(doc) {
        bulk.find({ "_id": doc._id }).updateOne({ 
            "$push": { "array2": { "$each": doc.array2 } }
        });
        count++;
    
        // send and drain once every 1000 documents
        if ( count % 1000 == 0 ) {
            bulk.execute();
            bulk = db.collection.initializeOrderedBulkOp();
        }
    });
    
    // If the counter is uneven then send
    if ( count % 1000 != 0 )
        bulk.execute();
    

    原来如此。您可以将聚合框架与 $map 这样的运算符一起使用,以便从数组中提取所需的元素,或者考虑到您并没有真正“聚合”任何东西,您可以使用类似的方法在代码中执行此操作。这里的主要情况是,无论您使用哪种语言,您都需要在代码中循环结果。

    当然,如果您可以只使用更改后的结果创建一个“新”集合,那么聚合的 $out 管道阶段可能非常适合您:

    db.collection.aggregate([
        { "$project": {
            "array1": 1,
            "array2": {
                "$map": {
                    "input": "array1",
                    "as": "el",
                    "in": "$$el.fld1"
                }
            }
        }},
        { "$out": "newcollection" }
    ]);
    

    简而言之,尽管您需要部分或全部这些技术来获得您正在寻找的更改后的收集结果。所以要么直接使用它,要么实现其中的一些。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-25
      • 2020-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-06
      相关资源
      最近更新 更多