2015-01-16 73 views
3

完全匹配的子文档很容易,但有没有一种方法可以精确地匹配集合中的整个文档?如何精确匹配整个文档?

我有很多类似的数据文件,而我只需要准确的,没有额外的数据

使用负$存在将不适合我,因为我不知道所有事先可能的领域相匹配。

+0

你究竟是什么意思的“完全匹配”的子文件?如果不知道那里所有可能的领域,你如何看待你?这听起来像混淆了我很不清楚。 –

+0

好,如果我正在查找文档{a:5}我不希望它匹配{a:5,b:1},只有{a:5} – Dracony

+0

您误解了我的示例。我说,如果我查询{a:1},我只需要文档是{a:1}而不是像{a:1,b:1} – Dracony

回答

2

我不认为这是可能的顾左右而言他,但可能的解决方案是散列文件。

保存时,总是创建文件的哈希:

var doc = {}; 
delete doc.hash; // never include the hash itself in the calculation 
doc.hash = crypto.createHash('sha256').update(JSON.stringify(doc)).digest(); 
db.collection.insert(doc); 

然后查询时,您可以通过哈希查询:

db.collection.find({ 
    hash: hash 
}) 

可能是讨厌的,如果你经常做的原子更新文件。

+0

这种吸引力,特别是因为你可以完全匹配子文档 – Dracony

+0

一个优雅的解决方案,应该不存在的问题。谢谢! –

-1

我真的不明白你的问题,你能解释一下吗?

如果你想要的文件没有一些字段,你可以使用$存在

举例来说,如果你有...

{a: 1 , b: "1", c: true } 
{a: 2, b: "2", c: false} 
{a: null, b: "3" } 

然后db.my_collection.find({a: {$exists: true}});发现

{a: 1 , b: "1", c: true } 
{a: 2, b: "2", c: false} 

而且db.my_collection.find({a: {$exists: false}});发现

{a: null, b: "3" } 
+0

这样的文档,我不能依赖$ exists,因为有太多可能领域。 – Dracony

0

不是一个理想的方法,但真正的唯一方法是在服务器上过滤掉这个问题,就是使用JavaScript评估运算符。确保它与传统查询一起使用,尽管至少从索引选择中获得了一些性能优势,因为JavaScript本身无法做到这一点。

考虑以下几点:

{ "a" : 1 } 
{ "a" : 1, "b" : 2 } 
{ "a" : 1, "b" : 2, "c" : 3 } 
{ "a" : 1, "b" : 2, "c" : 3, "d" : 4 } 

所以,现在你需要“第三”的文件只匹配。这里的基本代码的概念:

var query = { "a": 1, "b": 2, "c": 3 }; 
var string = ""; 

Object.keys(query).forEach(function(key) { 
    if (query[key].constructor.toString().match(/(Array|Object)/) == null) 
     string += key + query[key].valueOf().toString(); 
}); 

query['$where'] = 'function() { ' + 
    'var compare = ""; ' + 
    'var string = "' + string + '"; ' + 

    'var doc = this; ' + 
    'delete doc._id; ' + 

    'Object.keys(doc).forEach(function(key) { ' + 
     'if (doc[key].contructor.toString().match(/(Array|Object)/) == null) ||' + 
      'compare += key + doc[key].valueOf().toString(); ' + 
    '}); ' + 
    'return compare == string; ' + 
'};'; 

db.test.find(query); 

有些司机有更好的概念混用的外部变量转换成代码,但它给出了基本思路。

您需要根据所需的确切字段和值计算外部图片或哈希值,然后在服务器上使用相同的方法来计算当前文档字段中的值。自然地,_id总是被排除,因为它是唯一的。

你不需要子元素的签名,因为正如你所说的,你可以完全匹配那些纯粹在查询中的元素。所以这只是一个排除比较一代的问题。

通用查询参数将完成大部分工作,在这种情况下,可将其缩小到两个文档,理想情况下使用索引来完成。剩余的匹配是通过“强力”JavaScript评估完成的,因此只有与查询中的字段具有匹配签名的文档。