Firestore - Простое решение для полнотекстового поиска - PullRequest
1 голос
/ 31 мая 2019

Я знаю, что Firestore не поддерживает полнотекстовый поиск, и это дает нам решение использовать сторонние сервисы. Однако я нашел простое решение для простого «полнотекстового поиска», и я думаю, что это может помочь другим, кто не хочет использовать сторонние сервисы, как я, для такой простой задачи. Я пытаюсь найти название компании, которое сохраняется в коллекции Firestore под моим companyName, которое может быть в любом формате, например, «Моя удивительная компания». При добавлении новой компании с companyName или обновлении значения в companyName я также сохраняю searchName вместе с ним, значение которого совпадает с названием компании, но в нижнем регистре без пробелов

searchName: removeSpace(companyName).toLowerCase() 

removeSpace - моя простая пользовательская функция, которая удаляет все пробелы из текста

export const removeSpace = (string) => {
    return string.replace(/\s/g, '');
}

Это превращает название нашей компании в myawesomecompany , которое сохраняется в searchName

Теперь у меня есть функция пожарного депо для поиска компании, которая индексирует с помощью searchName и возвращает companyName. Минимальное поисковое значение - это искомое значение без последнего символа, а максимальное поисковое значение - искомое значение с добавленным «zzzzzzzzzzzzzzzzzzzzzzzz», преобразованным в нижний регистр. Это означает, что если вы ищете My Aw , то минимальное значение будет mya , а максимальное значение будет myawzzzzzzzzzzzzzzzzzzzzzzz

exports.handler = ((data) => {
const searchValue = data.value.replace(/\s/g, '').toLowerCase()
const minName = searchValue.substr(0, searchName.length-1)
const maxName = searchValue + "zzzzzzzzzzzzzzzzzzzzzzzz"
let list = []
const newRef = db.collection("user").where("profile.searchName", ">=", minName).where("profile.searchName", "<=", maxName)
return newRef.get()
.then(querySnapshot => {
    querySnapshot.forEach(doc => {
        list.push({ name: doc.data().profile.companyName})
    })
    return list
})
})

У меня не было времени полностью протестировать его, но пока он работает без проблем. Пожалуйста, дайте мне знать, если вы заметили что-то не так с этим. Теперь вопрос

Является ли символ "z" символом наибольшего значения в пожарном депо, или есть какой-либо другой более достойный способ добавить в максимальное значение поиска значение без добавления "zzzzzzzzzzzzz"?

Ответы [ 2 ]

1 голос
/ 01 июня 2019

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

"My Awesome Company"

в ...

{ my: true, awesome: true, company: true }

... и проверьте это.

При добавлении / обновлении свойства:

// save keywords on the user
let keywords = {}
companyName.split(' ').forEach(word => keywords[word.toLowerCase()] = true)

При запросе:

let searchKeywords = userInputString.split(' ').map(word => word.toLowerCase())

let collection = db.collection("user")
searchKeywords.forEach(keyword => { 
  collection = collection.where(`keywords.${keyword}` , '==' , true);
}); 
0 голосов
/ 02 июня 2019

С небольшой модификацией предыдущего ответа я сделал еще один простой текстовый поиск. Я сохраняю ключевое слово в массив вместо того, чтобы сохранять его в объекте, подобном этому

nameIndex: textIndexToArray(companyName)

где textIndexToArray - моя пользовательская функция

export const textIndexToArray = (str) => {
const string = str.trim().replace(/ +(?= )/g,'')
let arr = []
for (let i = 0; i < string.trim().length; i++) {
    arr.push(string.substr(0,i+1).toLowerCase());
}
return arr
}

, которые передают текст в массив. Например

"My Company"

вернет

[m, my, my , my c, my co, my com, my comp, my compa, my compan, my company]

с помощью nameIndex, сохраненного в firestore, мы можем просто запросить данные по имени nameIndex и вернуть companyName

exports.handler = ((data) => {
const searchValue = data.value.toLowerCase()
let list = []
const newRef = db.collection("user").where("nameIndex", "array-contains", searchValue)
return newRef.get()
.then(querySnapshot => {
    querySnapshot.forEach(doc => {
        list.push({ name: doc.data().companyName, })
    })
    return list
})
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...