Подтвердить что ты не робот

Поиск значения любого поля в MongoDB без явного называния его

Я просмотрел документацию MongoDB и перешел к этому вопросу, но не смог найти подходящего ответа. Итак, вот что я ищу. Предположим, у меня есть коллекция с такими элементами:

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

Я бы хотел найти элемент, выполнив поиск во всех (возможно, за исключением конечного числа;-)) полей. Другими словами: Если задан запрос, я НЕ знаю, в каком поле должен быть найден запрос.

В моем мышлении что-то вроде этого

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

даст мне примерный элемент.

Благодарим вас за помощь.

4b9b3361

Ответ 1

чтобы выполнить текстовый поиск по всем полям, сначала необходимо создать текстовый индекс для всех полей.

в качестве документации mongodb указывает:" Чтобы разрешить текстовый поиск во всех полях с содержимым строки, используйте спецификатор подстановки ($ **), чтобы индексировать все поля, которые содержат содержимое строки.

если вы работаете внутри оболочки mongo (которую вы выполняете из командной строки, вызывая "mongo" ), вы можете сделать это с помощью этой команды, где "коллекция" - это имя коллекции в db, которую вы хотите для использования.

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 в текстовом поиске здесь

Ответ 2

Этот ответ на похожий вопрос имеет ваше решение, которое я повторю здесь для полноты. Вы можете использовать оператор $where для запуска произвольного JavaScript на серверах MongoDB с оговоркой, что это будет намного медленнее, чем почти любой другой тип запроса. Для вашего примера это будет:

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

Ответ 3

Это невозможно без индивидуальной проверки документов на стороне приложения или при выполнении кода на стороне сервера. Рассмотрите возможность изменения вашей схемы:

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

Это, очевидно, имеет некоторые недостатки (производительность и политическая схема в основном), но позволят вам:

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

Ответ 4

К сожалению, ни один из предыдущих ответов не касается того факта, что mongo может содержать вложенные значения в массивах или вложенных объектах.

ЭТО ПРАВИЛЬНЫЙ ЗАПРОС:

{$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 (обе неэффективны, так как запрос использует больше ram и slow, так как в контексте функции уже есть загруженный объект)

Ответ 5

Вы можете сделать это с помощью рекурсивной функции:

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

Ответ 6

Используя $, где совпадает с выполнением полного сканирования таблицы и не может использовать индексы. Я также не мог заставить его работать, однако я нашел, что это сработало (это также эквивалентно полному сканированию таблицы):

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

где /needle/ - регулярное выражение для нахождения в значении doc[key]

Ответ 7

Для выполнения текстового поиска вам необходимо создать текстовые индексы для своей коллекции. Для получения дополнительной информации см. Документацию по mongo: индексирует текст

Ответ 8

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

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