Mongodb - Как найти строку в нескольких полях?
Использование Pymongo для этого сценария.
У меня есть Пользователь, у которого есть адрес электронной почты, first_name, last_name.
Я использую этот фрагмент 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 в first_name + last_name вместе.
как я могу это сделать?
Есть ли способ в монго, по запросу, объединить два в "полное имя", а затем искать полное имя?
Ответы
Ответ 1
Самый простой способ - добавить поле массива и заполнить его всеми вариантами, которые вы хотите выполнить. Индексируйте это поле массива.
Таким образом, вам нужен только один индекс, и ваш поиск по всем полям прост и не меняется, если вы хотите выполнить поиск по новому варианту поиска. Вы также можете нормализовать текст, который вы помещаете в массив поиска, например, нижний корпус, удаление пунктуации и т.д.
См. fooobar.com/questions/323243/...
Изменить: Документация MongoDB теперь охватывает поиск по ключевым словам и новый полнотекстовый поиск.
Ответ 2
У меня была та же проблема. Я уже использовал регулярный поиск по регулярному выражению, поэтому мое решение было:
генерирует вспомогательную коллекцию. Здесь я объединяю все соответствующие строки, например:
{
search_field: email + " " + first_name + " " + last_name,
ref_id: (id to real object)
}
Затем я использую regexp для создания того, что я могу найти:
// logic found here: http://stackoverflow.com/info/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");
Это также дает некоторую гибкость в отношении порядка.
Поиск не самый быстрый, так как он все еще использует регулярное выражение для всех элементов, но это нормально для меня. (Я также индексирую коллекцию на search_field.
Получение результатов также становится вложенным вызовом, поскольку сначала вам нужно получить нужные вам _ids, а затем вы можете запросить их так:
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("");
});
Это отредактированный код.. возможно, есть синтаксическая ошибка, как правило, она работает для меня.