我使用Mongoid和MongoDB v2.4.6在rails应用程序上有一个ruby。
我有以下MongoDB结构,embeds_many
片段的记录:
{
"_id" : "76561198045636214",
"fragments" : [
{
"id" : 76561198045636215,
"source_id" : "source1"
},
{
"id" : 76561198045636216,
"source_id" : "source2"
},
{
"id" : 76561198045636217,
"source_id" : "source2"
}
]
}
我正在尝试查找数据库中包含具有重复source_ids 的片段的所有记录。
我非常确定我需要使用$ elemMatch来查询嵌入式文档。
我试过了
Record.elem_match(fragments: {source_id: 'source2'})
有效,但不限制重复。
然后我尝试了
Record.elem_match(fragments: {source_id: 'source2', :source_id.with_size => 2})
不返回任何结果(但是是有效的查询)。 Mongoid产生的查询是:
selector: {"fragments"=>{"$elemMatch"=>{:source_id=>"source2", "source_id"=>{"$size"=>2}}}}
一旦有效,我需要将其更新为$ size是> 1.
这可能吗?感觉就像我非常接近。这是一次性的清理操作,因此查询性能不是太大的问题(但是我们确实需要更新数百万条记录!)
非常感谢任何帮助!
我已经能够达到预期的效果,但在测试中它太慢了(在我们的生产系统中运行需要数周时间)。问题是每条记录的双重查询(我们在生产中有大约3000万条记录)。
Record.where('fragments.source_id' => 'source2').each do |record|
query = record.fragments.where(source_id: 'source2')
if query.count > 1
# contains duplicates, delete all but latest
query.desc(:updated_at).skip(1).delete_all
end
# needed to trigger after_save filters
record.save!
end
答案 0 :(得分:1)
目前的方法存在的问题是标准的MongoDB查询表单实际上并没有过滤"嵌套数组文档以任何方式。这基本上是你需要的,以找到重复的"在你的文件中。
为此,MongoDB提供聚合框架可能是找到它的最佳方法。没有直接的" mongoid"查询的样式方法,因为它们面向现有的" rails"处理关系文件的方式。
您可以访问"轻便摩托车"通过类模型上的.collection
访问器形成:
Record.collection.aggregate([
# Find arrays two elements or more as possibles
{ "$match" => {
"$and" => [
{ "fragments" => { "$not" => { "$size" => 0 } } },
{ "fragments" => { "$not" => { "$size" => 1 } } }
]
}},
# Unwind the arrays to "de-normalize" as documents
{ "$unwind" => "$fragments" },
# Group back and get counts of the "key" values
{ "$group" => {
"_id" => { "_id" => "$_id", "source_id" => "$fragments.source_id" },
"fragments" => { "$push" => "$fragments.id" },
"count" => { "$sum" => 1 }
}},
# Match the keys found more than once
{ "$match" => { "count" => { "$gte" => 2 } } }
])
这会让你得到如下结果:
{
"_id" : { "_id": "76561198045636214", "source_id": "source2" },
"fragments": ["76561198045636216","76561198045636217"],
"count": 2
}
至少可以帮助你解决如何处理"重复问题"这里