【问题标题】:Replace multi value in correct field mongo [duplicate]替换正确字段mongo中的多个值[重复]
【发布时间】:2015-07-10 04:06:47
【问题描述】:

我有一个这样的示例 mongodb:

{
        "_id" : ObjectId("559e448dfb9fc95e5d00008c"),
        "title" : "Maps ",
        "link" : "https://www.youtube.com/embed/NmugSMBh_iI",
        "img" : "https://i.ytimg.com/vi/NmugSMBh_iI/default.jpg",
        "time" : "3:28",
        "des" : "Maroon 5 - Maps (Explicit)\r\n",
        "cat" : [
                "maroon5"
        ],
        "id" : 179,
        "date" : "2015-07-08T16:49:11+07:00"
}
{
        "_id" : ObjectId("559e451afb9fc95e5d00008d"),
        "title" : "Animals",
        "link" : "https://www.youtube.com/embed/qpgTC9MDx1o",
        "img" : "https://i.ytimg.com/vi/qpgTC9MDx1o/default.jpg",
        "time" : "4:40",
        "des" : "Maroon 5 - Animals\r\n",
        "cat" : [
                "maroon5"
        ],
        "id" : 180,
        "date" : "2015-07-08T16:49:11+07:00"
}

现在我想在每个“链接”字段中将这个字符串“embed/”替换为“watch?v=”,如下所示:

"link" : "https://www.youtube.com/watch?v=/NmugSMBh_iI"

我该怎么做?

【问题讨论】:

  • 不是没有循环。 MongoDB 更新无法自动检查字段的现有值。您需要阅读每个文档以获取值,将其更改并将$set 属性更改为更改后的值。

标签: regex mongodb mongodb-query


【解决方案1】:

您将不得不遍历它并一一更改它们。 您可以使用以下代码在数据库中进行更改,但或者,您可以使用 MongoDB 的支持库来获得相同结果的任何语言。

var cursor = db.videos.find();
while ( cursor.hasNext() ) {
   var current = cursor.next();
   db.videos.update({_id: current._id}, {$set: {link: current.link.replace('embed/','watch?v=')}})
}

【讨论】:

    【解决方案2】:

    如上所述,您需要循环收集结果,以便能够读取要修改的值。 MongoDB 更新运算符不支持“就地”执行此操作,并且目前不支持“regexReplce”运算符。虽然会很好。

    您最有效的方法是使用"Bulk" 操作API,并通过$regex 进行一些查询过滤,以确保您只更新那些需要更新的项目:

    var bulk = db.tube.initializeUnorderedBulkOp(),
        count = 0;
    
    db.tube.find({ 
       "link": /(youtube\.com)(\/embed)/ 
    }).forEach(function(doc) {
        doc.link = doc.link.replace( 
            new RegExp("(youtube\.com)(\/embed\/)"), 
            new RegExp("$1/watch\?v=") );
    
        bulk.find({ "_id": doc._id }).updateOne({ "$set": { "link": doc.link } });
        count++;
    
        // Only send operations to server once in 1000 ops. And re-init.
        if ( count % 1000 == 0 ) {
            bulk.execute();
            bulk = db.tube.initializeUnorderedBulkOp();
        }
    });
    
    // Drain any queued operations
    if ( count % 1000 != 0 )
        bulk.execute();
    

    这是您最快的更新方式,因为请求是“批量”处理的,这意味着进出服务器的流量更少。因此,速度更快。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-17
      • 2015-09-23
      相关资源
      最近更新 更多