为什么这个db.eval - > array.push对某些记录执行两次?

时间:2014-08-06 01:08:44

标签: arrays mongodb

我想在匹配简单选择器的记录中向数组添加一个对象元素,所以我运行了这个查询:

db.eval(function() { 
    db.companies.find({exchange: 'OTC'}).forEach(function(c) {
          c.links.push({
            url: 'http://www.otcmarkets.com/stock/' + c.symbol + '/profile',
            text: 'OTCMarkets.com'
          });
          db.companies.save(c);
    });
});

在与选择器匹配的大约10,000条记录中,大约1100条记录最终在阵列末尾推送了两个链接。有什么可能导致这种情况?大约1000个有一个空的links数组,但是大约有100个数组有一个或多个元素:

{
"_id": "...",
...
"exchange": "OTC",
"links": [
    {
        "text": "Website",
        "url": "..."
    },
    {
        "text": "OTCMarkets.com",
        "url": "http://www.otcmarkets.com/stock/GREN/profile"
    },
    {
        "text": "OTCMarkets.com",
        "url": "http://www.otcmarkets.com/stock/GREN/profile"
    }
],
"name": "GreenSmart Corp.",
...
}

大多数其他记录正确地只推送了一个数组元素:

{
"_id": "6WiXSoefPtqJdmzxa",
...
"exchange": "OTC",
...
"links": [
    {
        "text": "Website",
        "url": "..."
    },
    {
        "text": "Financial Information",
        "url": "..."
    },
    {
        "text": "Executives",
        "url": "..."
    },
    {
        "text": "OTCMarkets.com",
        "url": "http://www.otcmarkets.com/stock/SFEF/profile"
    }
],
"name": "Santa Fe Financial Corp.",
...
}

为了简洁起见,我省略了记录中的字段,但是我无法理解为什么有些人会将OTCMarkets链接元素推送一次,而其他人则会两次。

Mongo 2.6.3。

2 个答案:

答案 0 :(得分:2)

因为你的排序:

 db.companies.find({exchange: 'OTC'})

这是naural排序,并且由于您的更新很可能不适用于那些1,100,这导致一些文档移动到MongoDB内部链接列表的末尾,这是默认的排序顺序;因此,您将收到重复的文件。

使用_id或其他类似的东西对查询进行排序。

答案 1 :(得分:2)

你的问题被劫持了一些侧面讨论,但我想在答案中修正我的错误,以免误导你或其他任何人。 $isolated运算符不会帮助您,因为它是您自己的更新,导致文档移动(因为它们更改大小),然后再次使用集合扫描重新发现。使用Sammaye建议的那种。

另外,请不要使用$isolated,除非您确定需要单独更新;也不要忘记$isolated更新虽然是孤立的,但不是原子的。

最后,请不要使用db.eval。它在docs中讨论了一系列限制,并且应该由聚合框架替换并执行> 1调用数据库。