2011-07-22 17 views
34

我查看了MongoDB文档并搜索了这个问题,但找不到合适的答案。所以,这就是我要找的。 假设我有这样的元素集合:在没有明确命名的情况下搜索MongoDB中的任何字段的值

{ 
    "foo" : "bar", 
    "test" : "test", 
    "key" : "value", 
} 

我想达成的目标是在所有搜索(也许除了有限多个;-))领域找到一个元素。换句话说:给定一个查询,我不知道应该在哪个字段中找到查询。

在我的思路是这样的

db.things.find({_ANY_ : "bar"}) 

会给我出了示例元素。

谢谢你的帮助。

+0

因此,你需要什么是像全文搜索,这是不是原生在MongoDB中实现,也请参阅:http://www.mongodb.org/display/DOCS/Full+Text+Search+in+Mongo – asaaki

+0

我不认为这是一个文本搜索问题。这是按价值查询。他们都同意这样一个事实,即在Mongo中没有原生支持;) –

+1

@asaaki:与此同时,Mongo已经实现了[全文搜索](http://docs.mongodb.org/manual/core/index-文本/)。让我们删除我们的评论。 –

回答

21

如果不单独检查应用程序文档或通过服务器端代码执行,这是不可能的。考虑更改架构:

{params:[{field:"foo", value:"bar"}, {field:"test", value:"test"}, {field:"key", value:"value"}]} 

这显然有一些缺点(性能和poluted模式居多),但只会让你需要通过什么:

db.things.find({'params.value':"bar"}) 
+4

事实上正确答案如何有两个降价? –

+0

如何根据此模式的特定字段进行排序?我的意思是像OP中的.sort({foo:1})。 – runTarm

+1

你没有。 find({'params.field':“foo”})。sort({'params.value':1})由于数组的工作方式不同等。 –

2

你可以用递归函数做到这一点:

var recursiveSearch = function(query) { 
    db.test_insert.find().forEach(function(items) { 
     var i = 0; 
     var recursiveFunc = function(itemsArray, itemKey) { 
      var itemValue = itemsArray[itemKey]; 
      if(itemValue === query) { 
       printjson(items); 
      }  

      if(typeof itemValue === "object") { 
       Object.keys(itemValue).forEach(function(itemValueKey) { 
        recursiveFunc(itemValue, itemValueKey); 
       }); 
      } 
     }; 
     Object.keys(items).forEach(function(item){ 
      recursiveFunc(items, item); 
     }); 
    }); 
}; 

recursiveSearch('your string'); 
2

要进行文本搜索,您必须为您的收藏创建文本索引。 欲了解更多信息,请查看蒙戈文档:indexes text

10

This answer到类似的问题有解决方案,我将在这里重复的完整性。您可以使用$where运算符在MongoDB服务器上运行任意JavaScript,但需要注意的是这比其他类型的查询要慢得多。举例来说,它将是:

db.things.find({$where: function() { 
    for (var key in this) { 
     if (this[key] === "bar") { 
      return true; 
     } 
     return false; 
    } 
}}); 
16

要在所有字段上进行文本搜索,首先必须在所有字段上创建文本索引。

作为mongodb documentation指示:“为了允许在所有字段中使用字符串内容进行文本搜索,请使用通配符说明符($ **)来索引包含字符串内容的所有字段。

如果你蒙戈外壳(这可以通过调用“蒙戈”在命令行中执行)内工作,那么你可以用这个命令,其中“集”是在数据库中收集的名字做你想用。

db.collection.createIndex({ "$**": "text" },{ name: "TextIndex" })

第二个目的,即{name:"TextIndex"},是可选的...你实际上并不需要给索引的名称,因为只能有每收集一个单一的文本索引(在一个时间。如果你愿意,你可以删除索引并创建新索引)。

一旦你创造的所有字段的文本索引,你可以用下面的查询对象的简单文本搜索: { $text : { $search: <your string> } }

所以,如果你正在写一个javascript函数,你可以这样做:

var cursor = db.collection(<collection_name>).find({ $text: { $search: <your string> } });

上的各种方式来控制搜索,查看文字MongoDB的文档的详细信息搜索here

+0

如果字符串围绕某个单词转义了,那么它会将搜索转变为“和”搜索,而不是“或”搜索。{$ text:{$ search:“\”jim \“\”habit \“ “}}在文本索引中找到'jim'和'habit'的所有记录 –

0

使用$where与执行全表扫描相同,不能使用索引。我也无法得到它的工作,但我没有找到这个工作(它也执行全表扫描的等价物):

db.collection.find().forEach(function(doc){ 
for (var key in doc) { 
    if (/needle/.test(doc[key])) 
     printjson(doc); 
    } 
}); 

其中/needle/是一个正则表达式中的doc[key]

5
价值发现

不幸的是,以前的答案都没有解决mongo可以在数组或嵌套对象中包含嵌套值的事实。

这是正确的QUERY:

{$where: function() { 
    var deepIterate = function (obj, value) { 
     for (var field in obj) { 
      if (obj[field] == value){ 
       return true; 
      } 
      var found = false; 
      if (typeof obj[field] === 'object') { 
       found = deepIterate(obj[field], value) 
       if (found) { return true; } 
      } 
     } 
     return false; 
    }; 
    return deepIterate(this, "573c79aef4ef4b9a9523028f") 
}} 

由于调用的typeof上数组或嵌套的对象将返回“对象”,这意味着该查询将迭代上的所有嵌套的元素,并且将通过所有的然后,直到迭代带有值的键将被找到。

您可以使用嵌套值检查以前的答案,结果将远离期望。

字符串化整个对象的性能低得多,因为它必须遍历所有内存扇区,逐个尝试匹配它们。并在RAM内存中创建一个对象作为字符串的副本(既低效,因为查询使用更多的内存和缓慢,因为功能上下文已经有一个加载的对象)

+0

我们可以重写if(obj [field] == value)like - if(typeof obj [field] =='string'&& obj [field] .contains(/ value /))。它给出更准确的搜索结果 –

-3
{ 
    "foo" : "bar", 
    "test" : "test", 
    "key" : "value", 
} 

db.collection_name.find({'foo':"bar"}) 
+0

这不是OP所要求的。问题是如何找到没有指定字段名称的项目。 – user2223059

相关问题