#javascript #regex #mongodb
#javascript #регулярное выражение #mongodb
Вопрос:
Мне нужно отфильтровать список имен, используя regex
.
Я сохранил данные в этом формате
[
{
"firstName": "Jhon",
"lastName": "Doe",
},
...
]
Пользователь может ввести полное имя, имя или фамилию. Но мне нужно сопоставить их все. Мой запрос mongo выглядит следующим образом (я использовал Loopback 4
для создания этого запроса, но идея очевидна)
{
or: [{firstName: new RegExp(searchKey, 'i')}, {lastName: new RegExp(searchKey, 'i')}],
};
Но это не соответствует, когда пользователь вводит jhon doe, но работает, когда вводится только имя или фамилия.
Мой вопрос в том, есть ли способ сопоставить часть строки с регулярным выражением?
ожидается, что будет возвращено успешное совпадение для всех «jhon», «doe», «jhon doe» и «jhondoe»
Комментарии:
1.
searchKey.split(/s/g).join('|')
..?2. Да, это решение. Но предположим, что пользователь вводит «jhondoe»??
3. Это не будет допустимой частью имени пользователя ни по каким критериям, следовательно, это должно завершиться неудачей. Вы могли бы добавить
'|' searchKey
в конец строки, чтобы включить также исходный ключ поиска, но я бы отказался от этой альтернативы.4. Согласен, если это имена пользователей. но это имена пользователей, и требуется найти совпадающие имена. Мне нужно знать, может ли это быть реализовано с помощью каких-либо регулярных выражений. Кстати, ваш приведенный выше комментарий пока работал
5. Рассматривали ли вы текстовый индекс ?
Ответ №1:
Я не знаю, возможно ли написать общее регулярное выражение, которое может это сделать, я создал алгоритм грубой силы для построения регулярного выражения.
let text = `[
{
"firstName": "Jhon",
"lastName": "Doe",
},
...
]`;
// Brute force
let key = "jhondoe";
let keyArr = [];
for (let i = 0; i < key.length; i ) {
let a = key.slice(0, i);
let b = key.slice(i);
a amp;amp; keyArr.push(a);
b amp;amp; keyArr.push(b);
}
let keySearch = keyArr.join("|");
console.error(keySearch);
let regex = new RegExp(`"(?:first|last)Name": "(${keySearch})"`, `gim`);
let matches = text.match(regex);
console.log(matches);
Комментарии:
1. ВАУ !!!!.. это грубо. вы можете получить неожиданные результаты, поскольку он также сравнивает каждую букву.. Но я понял, что мой вопрос заслуживает этого ответа. Я не уверен, должен ли я принять этот ответ или нет, но он правильный
2. Возможно, измените, чтобы принять целое слово, или, если это подстрока, вы должны сопоставить имя и фамилию одновременно.
Ответ №2:
Теперь я создал полный код, который учитывает несколько вещей. К сожалению, если у кого-то есть имя jhon doe, а у кого-то еще есть имя jhond oe, этот код примет его.
Основная идея состоит в том, чтобы проверить, является ли ключ именем ИЛИ фамилией. В противном случае, если оно содержит пробелы, все, что находится перед первым пробелом, является FirstName , а все, что после, — LastName . В противном случае, используя грубую силу, он проверяет все комбинации FirstName и LastName, левая подстрока — fisrtName, правая подстрока — LastName.
let text = `[
{
"firstName": "Jhon",
"lastName": "Doe",
},
...
]`;
const nameValidator = (key, text) => {
// Attempts to check whether the entire key received is a first or last name.
let regexKey = new RegExp(`"(?:first|last)Name": "${key}"`, `gim`);
if (regexKey.test(text)) {
return true;
} else if (key.includes(" ")) {
// if the key has spaces, we already know the first and lastName
// if the key has more than one space, everything after the first space goes to lastName
let [_, a, b] = /^(w ) (.*)$/.exec(key);
let regexFirstLastName = new RegExp(`"firstName": "${a}",(\s|\t|\n)*"lastName": "${b}",`, `gim`);
if (regexFirstLastName.test(text)) {
return true;
}
} else {
// Search by brute force for the division between first and last name
for (let i = 1; i < key.length; i ) {
let a = key.slice(0, i);
let b = key.slice(i);
console.log(`Trying name="${a}" and lastname="${b}"`);
let regexFirstLastName = new RegExp(`"firstName": "${a}",(\s|\t|\n)*"lastName": "${b}",`, `gim`);
if (regexFirstLastName.test(text)) {
return true;
}
}
}
return false;
}
const keys = ["jhon", "doe", "jhon doe", "jhondoe", "auehuaheuahe"];
for (key of keys) {
console.log(key, nameValidator(key, text));
console.log("=======================n");
}