Mongodb - Как найти строку в нескольких полях? - PullRequest
18 голосов
/ 23 ноября 2011

Использование Pymongo для этого сценария.

У меня есть пользователь, у которого есть электронная почта, имя, фамилия и фамилия.

Я использую этот фрагмент Pymongo:

user_found = users.find({'$or':[
            {'email':{'$regex':searchString, '$options':'i'}},
            {'first_name':{'$regex':searchString, '$options':'i'}},
            {'last_name':{'$regex':searchString, '$options':'i'}}]})

этот пример работает, если я хочу найти searchString в:

  • электронная почта или
  • first_name или
  • last_name

теперь мне нужно найти searchString в сочетании имя_фамилия + фамилия.

как я могу это сделать? Есть ли способ в монго, посредством запроса, объединить их в «полное имя» и затем искать полное имя?

Ответы [ 2 ]

15 голосов
/ 23 ноября 2011

Самый простой способ - добавить поле массива и заполнить его всеми вариантами поиска.Индексируйте это поле массива.

Таким образом, вам нужен только один индекс, и ваш поиск по всем полям прост и не меняется, если вы хотите выполнить поиск по какому-либо новому варианту поиска.Вы также можете нормализовать текст, который вы помещаете в массив поиска, например, нижний регистр, удаляя пунктуацию и т. Д.

См. https://stackoverflow.com/q/8206188/224370

Редактировать: Документация MongoDBтеперь включает поиск по ключевым словам и новую функцию полнотекстового поиска .

1 голос
/ 28 января 2015

У меня была такая же проблема.Я уже использовал поиск по регулярным выражениям, поэтому мое решение было:

создать вспомогательную коллекцию.Здесь я объединяю все соответствующие строки, такие как:

{
    search_field: email + " " + first_name + " " + last_name,
    ref_id: (id to real object)
}

Затем я использую регулярное выражение для создания того, что мне разрешено искать:

// logic found here: http://stackoverflow.com/questions/10870372/regex-match-if-string-contain-all-the-words-or-a-condition
var words = query.split(/[ ,]+/);
var regstr = "";
for (var i = 0; i < words.length; ++i) {
    var word = words[i];
    regstr += "(?=.*?\\b" + word + ")";
}
regstr += "^.*$";
regex = new RegExp(regstr, "i");

Это также дает некоторую гибкость в отношенииorder.

Поиск не самый быстрый, так как он все еще использует регулярные выражения для всех элементов, но для меня это нормально.(Я также индексирую коллекцию в поле поиска.

Получение результатов также становится вложенным вызовом, поскольку сначала вам нужно получить действительно нужные _id, а затем вы можете запросить их, например, так:

connection.find({ "search_field" : regex }, { _id: 0, ref_id: 1 }, { limit: limit, skip: start }).toArray(function (err, docs) {
    if (err) throw err;
    // map array of documents into simple array of ids
    var ids = [];
    for (var i = 0; i < docs.length; ++i)
    {
        var doc = docs[i];
        ids.push(doc.ref_id);
    }
    if (ids.length > 0)
        MongooseEmails.find({ "_id": { $in: ids } }, function (err, docres) {
            if (err) throw err;
            res.send(JSON.stringify(docsres));
        });
    else
        res.send("");
});

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...