在 MongoDB 中搜索任何字段的值而不显式命名它

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6790819/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 12:10:58  来源:igfitidea点击:

Searching for value of any field in MongoDB without explicitly naming it

searchmongodbfield

提问by Max L.

I looked through the MongoDB documentation and googled this question but couldn't really find a suitable answer. So, here is what I'm looking for. Assume I have a collection with elements like this:

我查看了 MongoDB 文档并在 google 上搜索了这个问题,但找不到合适的答案。所以,这就是我要找的。假设我有一个包含以下元素的集合:

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

What I'd like to achieve is find an element by searching in all (maybe except for finitely many ;-) ) fields. In other words: Given a query, I do NOT know in which field the query should be found.

我想要实现的是通过在所有(可能除了有限多个 ;-) )字段中搜索来找到一个元素。换句话说:给定一个查询,我不知道应该在哪个字段中找到查询。

In my thinking something like this

在我的想法是这样的

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

would give me the example element.

会给我示例元素。

Thank you for your help.

感谢您的帮助。

回答by dave adelson

to do a text search on all fields, you first must create a text index on all fields.

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

as the mongodb documentationindicates, "To allow for text search on all fields with string content, use the wildcard specifier ($**) to index all fields that contain string content."

正如mongodb 文档所指出的那样,“要允许对所有包含字符串内容的字段进行文本搜索,请使用通配符说明符 ($**) 来索引包含字符串内容的所有字段。”

if you are working inside the mongo shell (which you execute from the command line by calling 'mongo'), then you can do it with this command, where 'collection' is the name of the collection in the db you want to use.

如果您在 mongo shell 中工作(通过调用 'mongo' 从命令行执行),那么您可以使用此命令执行此操作,其中 'collection' 是您要使用的数据库中集合的名称。

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

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

the second object, i.e. {name:"TextIndex"}, is optional...you don't actually need to give the index a name, since there can only be a single text index per collection (at a time...you can drop indexes and create new ones if you want).

第二个对象,即{name:"TextIndex"},是可选的......你实际上不需要为索引命名,因为每个集合只能有一个文本索引(一次......你可以删除索引并创建新索引如果你想)。

once you have created a text index on all fields, you can do a simple text search with the following query object: { $text : { $search: <your string> } }

在所有字段上创建文本索引后,您可以使用以下查询对象进行简单的文本搜索: { $text : { $search: <your string> } }

so, if you are writing a javascript function you might do something like:

因此,如果您正在编写 javascript 函数,您可能会执行以下操作:

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

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

for more info on the various ways to control the search, see the mongodb documentation on text searching here

有关控制搜索的各种方法的更多信息,请参阅有关文本搜索的 mongodb 文档here

回答by Tom Panning

This answerto a similar question has your solution, which I'll repeat here for completeness. You can use the $whereoperator to run arbitrary JavaScript on the MongoDB server(s), with the caveat that this will be much slower than almost any other kind of query. For your example, it would be:

This answerto a similar question有您的解决方案,为了完整起见,我将在此处重复。您可以使用该$where运算符在 MongoDB 服务器上运行任意 JavaScript,但需要注意的是,这比几乎任何其他类型的查询都要慢得多。对于您的示例,它将是:

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

回答by Remon van Vliet

This is not possible without individually inspecting documents app-side or through server-side code execution. Consider changing your schema to :

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

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

This obviously has some downsides (performance and poluted schema mostly) but will allow what you need through :

这显然有一些缺点(主要是性能和污染模式),但可以通过以下方式满足您的需求:

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

回答by twboc

Sadly, none of the previous answers address the fact that mongo can contain nested values in arrays or nested objects.

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

THIS IS THE CORRECT 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")
}}

Since calling typeof on array or nested object will return 'object' this means that the query will iterate on all nested elements and will iterate through all of then until the key with value will be found.

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

You can check previous answers with a nested value and the results will be far from desired.

您可以使用嵌套值检查以前的答案,结果将与预期相去甚远。

Stringifying the whole object is far less performant since it has to iterate through all memory sectors one by one trying to match them. And creates a copy of the object as a string in ram memory (both inefficient since query uses more ram and slow since function context already has a loaded object)

字符串化整个对象的性能要低得多,因为它必须一一遍历所有内存扇区以尝试匹配它们。并将对象的副本创建为 ram 内存中的字符串(效率低下,因为查询使用更多的 ram 和慢,因为函数上下文已经加载了对象)

回答by Waddles

Using $whereis the same as doing a full table scan and cannot use the indexes. I also could not get it working, however I did find this worked (it also does the equivalent of a full table scan) :

使用$where与进行全表扫描相同,不能使用索引。我也无法让它工作,但是我确实发现这有效(它也相当于全表扫描):

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

where /needle/is a regular expression to find in the value of doc[key]

哪里/needle/是一个正则表达式来查找的值doc[key]

回答by RoXuS

You can do it with a recursive function:

您可以使用递归函数来做到这一点:

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');

回答by Salim Hamidi

To do text search, you have to create text indexes for your collection. For more information, look at mongo documentation :indexes text

要进行文本搜索,您必须为您的集合创建文本索引。有关更多信息,请查看 mongo 文档:索引文本

回答by rahul

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

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