我正在编写一个数据库层,其中 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 } )
请注意,"new"查询会自动计算出来。
但是,由于 bug https://jira.mongodb.org/browse/SERVER-1243 ,我基本上完蛋了。
(请注意,插入始终是一个简单的操作,意味着一个简单的 $push (那里没有问题),而删除是一个需要对 _children 进行 $pull 的操作($pull 接受一个过滤器来处理数组。所以,那里也没有问题)。唯一的问题是批量更新。)
现在:
由于以下几个原因,我无法加载完整文档并手动更改所有条目:(1) 性能:我需要对每个匹配的记录运行更新,可能是 100 万条; (2) 这实际上是不可能的,因为我没有办法在加载的文档上“重新运行”查询(可能涉及正则表达式等)
我无法重复更新操作,直到获得零更新(它们都已更改),因为如果更改也匹配,它将永远执行(如果您将 'perth' 更改为 'perth2',并匹配以 'p' 开头的任何内容。
但是,我确实需要这个功能,但我只是不知道如何做到这一点。
除了请求 MongoDB 人员解决这个问题之外,你们还有什么想法吗?这是 Mongo 数组更新的另一个弱点?
最佳答案
因此,考虑到您正在“批量更新”并且这可能是一次性操作,您可以考虑使用 db.eval()
像这样:
db.eval(function() {
db.collection.find({}).forEach(function(doc) {
doc._children.forEach(function(item) {
item.ucCountry = item.country.toUpperCase;
});
db.collection.update(
{ "_id": doc._id },
{ "$set": { "_children": doc._children } }
);
});
})
所以这几乎是标准循环,但这次它在服务器上运行。您甚至可以仅针对要更改的数组元素添加 $set 操作,以节省更多开销。
请注意,请阅读文档。在执行更新期间,您将锁定数据库进行写入,并阻止所有其他 JavaScript 操作,例如“mapReduce”。但这是最快的方法。
关于arrays - 解决 MongoDB 中的 bug #1243 的最佳方法(使用位置运算符更新数组中的所有项目),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22420712/