Arrays 在MongoDB中绕过bug#1243的最佳方法(使用位置运算符更新数组中的所有项)

Arrays 在MongoDB中绕过bug#1243的最佳方法(使用位置运算符更新数组中的所有项),arrays,mongodb,Arrays,Mongodb,我正在编写一个数据库层,其中1:n条记录缓存在一个_children字段中。 因此,如果你有人: { id: 1, name: 'Tony', surname: 'Mobily', _children: { addresses: [], } }, { name: 'Chiara', surname: 'Mobily', _children: { addresses: [], } } 然后将记录添加到地址: { id: 100 p

我正在编写一个数据库层,其中1:n条记录缓存在一个_children字段中。 因此,如果你有人:

{   
  id: 1,
  name: 'Tony',
  surname: 'Mobily',
  _children: {
    addresses: [],
  }
},
{
  name: 'Chiara',
  surname: 'Mobily',
  _children: {
    addresses: [],
  }
}
然后将记录添加到地址:

{
  id: 100
  personId: 1,
  street: 'Some street',
  country: 'Australia',
}

{
  id: 101
  personId: 1,
  street: 'Some other street',
  country: 'Australia',
}
正确的记录会在“人”中自动更新:

{   
  id: 1,
  name: 'Tony',
  surname: 'Mobily',
  _children: {
    addresses: [
      {
        id: 100
        personId: 1,
        street: 'Some street',
        country: 'Australia',
      },

      {
        id: 101
        personId: 1,
        street: 'Some other street',
        country: 'Australia',
      }

    ],
  }
},
我的图层还存储所有文本字段的大写版本,并自动运行不区分大小写的搜索等。它还处理“查找”字段,并自动填充它们

当您对地址字段执行批量更新时,它还会对“父”字段运行更新,以便所有内容都同步。一切都很好

除非您尝试对地址表进行大规模更新

例如:

addresses.update( { country: 'Australia' }, { street: 'Something else' }, { multi: true } )
完成此操作后,我还通过以下方式对每个“父”表(在本例中为
people
)运行查询:

people.update( { _children.country: 'Australia'}, { '_children.addresses.$.street': 'Something else' }, { multi: true } )
请注意,“新”查询是自动计算出来的

然而,由于bug,我基本上完蛋了

(请注意,插入操作始终是一个简单的$push操作(这里没有问题),删除操作需要$pull on_children($pull接受一个过滤器来处理数组。因此,这里也没有问题)。唯一的问题是批量更新。)

现在:

  • 我无法加载完整文档并手动更改所有条目,原因如下:(1)性能:我需要对每个匹配的记录运行更新,可能是100万;(2) 这实际上是不可能的,因为我没有办法对加载的文档“重新运行”查询(可能涉及regexp等)

  • 我不能重复更新操作,直到我得到零个更新(它们都已更改),因为如果更改也匹配,它将永远匹配(如果您将“perth”更改为“perth2”,并匹配以“p”开头的任何内容)

但是,我真的需要这个功能,我就是不知道怎么做

你们有什么想法,除了请求蒙哥大的家伙来解决这个问题,这还是Mongo的数组更新的另一个弱点吗?

< P>所以考虑到你是“大容量更新”,这可能是一次性的操作,你可以考虑这样使用:

db.eval(函数(){
db.collection.find({}).forEach(函数(doc){
doc.\u children.forEach(功能(项目){
item.ucCountry=item.country.toUpperCase;
});
db.collection.update(
{u id:doc.\u id},
{“$set”:{“_children”:doc._children}
);
});
})
这几乎是标准循环,但这次它在服务器上运行。您甚至可以为正在更改的数组元素添加$set操作,以节省更多的开销


但请注意阅读文档。执行更新期间,您将锁定数据库进行写入,并阻止所有其他JavaScript操作,如“mapReduce”。但这是实现这一点的最快方法。

失败,但任何改变模式的方法都无法适应。这是替换整个阵列的唯一方法。您可以查看处理文档的
db.eval()
表单,如示例所示。但是没有。没有其他方法可以更新数组的所有元素。我可以使用
db.eval()
以原子方式更改整个数组吗?另外,如果我要替换整个数组,可以说我仍然无法“按照查询”进行操作。。。正确的?(或者,我需要使用Javascript重新应用我的mongo过滤器…(我也尝试了$elemMatch:同样的问题,同样的结果…)对不起,AFK有一段时间了。我希望下面的例子清楚了这个词的用法。为之前误读你的要求道歉。别担心,伙计。。。来自珀斯的问候:)请注意,这不是一个bug,因为MongoDB中从未存在过该功能-这是对一个新功能的请求。这看起来很有希望,直到我意识到我正在使用MongoDB作为服务,我怀疑eval()是一个选项:(看起来我被卡住了!当有人使用我的图层对另一个1:n的子表进行大规模更新时,我可能会抛出错误。但是……它很糟糕。Mongo对我的用例来说真是太棒了……哦,好吧。@Merc哪个服务提供商?我怀疑你做不到。这正是它有用的原因。功能是什么(从客户端或驱动程序)发送“JavaScript”参数到服务器。打包的代码在服务器内部执行。除非您使用应用程序中的REST API(除非您有遗留代码,否则不要这样做)您实际上使用的是本机驱动程序,那么是的,它将得到支持。我不知道用这种方式锁定API调用的方法。我可能错了。但您应该检查。+不要等待其他答案。@事实上。这是测试。将mongo shell连接到托管数据库。在shell中键入以下内容:
db.eval(function(){return“Hello”}
。如果您没有收到错误并得到响应,那么它可以工作。否则,请检查权限以查看是否可以启用它。顺便说一句,从驱动程序调用,包含JavaScript的参数实际上是一个字符串。
db.eval(function(){return“Hello”})3月15日19:50:02.301{“ok”:0,“errmsg”:“unauthorized”}在src/mongo/shell/db.js:571,正如我担心的那样,没有可用的db.eval。呃…db.eval不可用有一个很好的理由-它不应该用于任何事情。它对性能有害,因为它会运行Javascript,所以您可以在应用程序中执行任何操作。