Я хочу добавить простое поле поиска, хотел бы использовать что-то вроде
collectionRef.where('name', 'contains', 'searchTerm')
Я пробовал использовать where('name', '==', '%searchTerm%')
, но ничего не вернуло.
firebase
google-cloud-firestore
безопасный
источник
источник
Ответы:
Там нет такого оператора, разрешенных из них является
==
,<
,<=
,>
,>=
.Вы можете фильтровать только по префиксам, например, для всего, что начинается между ними,
bar
иfoo
вы можете использоватьcollectionRef.where('name', '>=', 'bar').where('name', '<=', 'foo')
Для этого вы можете использовать внешний сервис, такой как Algolia или ElasticSearch.
источник
tennis
, но на основе доступных операторов запроса получить эти результаты невозможно. Комбинировать так>=
и<=
не получается. Конечно, я могу использовать Algolia, но я мог бы просто использовать его с Firebase для выполнения большинства запросов, и мне не нужно было переключаться на Firestore ...Я согласен с ответом @Kuba, но все же необходимо добавить небольшое изменение, чтобы он отлично работал для поиска по префиксу. вот что сработало для меня
Для поиска записей, начинающихся с имени
queryText
collectionRef.where('name', '>=', queryText).where('name', '<=', queryText+ '\uf8ff')
.\uf8ff
Используемый в запросе символ - это очень высокий код в диапазоне Unicode (это код области частного использования [PUA]). Поскольку он находится после большинства обычных символов в Юникоде, запрос соответствует всем значениям, начинающимся сqueryText
.источник
Хотя ответ Кубы верен в том, что касается ограничений, вы можете частично эмулировать это с помощью структуры, подобной множеству:
Теперь вы можете запросить
Это работает, потому что Firestore автоматически создает индекс для каждого поля. К сожалению, это не работает напрямую для составных запросов, потому что Firestore не создает составные индексы автоматически.
Вы все еще можете обойти это, сохраняя комбинации слов, но это быстро становится ужасно.
Вам все же, вероятно, будет лучше с внешним полнотекстовым поиском .
источник
where
Хотя Firebase явно не поддерживает поиск термина в строке,
Firebase (сейчас) поддерживает следующее, которое решит как в вашем, так и во многих других случаях:
По состоянию на август 2018 года они поддерживают
array-contains
запросы. Видеть: Https://firebase.googleblog.com/2018/08/better-arrays-in-cloud-firestore.htmlТеперь вы можете установить все ключевые термины в массив в виде поля, а затем запросить все документы, в которых есть массив, содержащий «X». Вы можете использовать логическое И для дальнейших сравнений для дополнительных запросов. (Это связано с тем, что firebase в настоящее время не поддерживает составные запросы для нескольких запросов, содержащих массив поэтому запросы сортировки `` И '' должны выполняться на стороне клиента)
Использование массивов в этом стиле позволит оптимизировать их для одновременной записи, что приятно! Не проверял, поддерживает ли он пакетные запросы (документы не говорят), но я бы поспорил, что он поддерживает, так как это официальное решение.
Использование:
источник
Search term
обычно понимается как целый термин, разделенный пробелами, знаками препинания и т. Д. С обеих сторон. Если выabcde
сейчас погуглите, вы найдете результаты только для таких вещей, как%20abcde.
или,,abcde!
но неabcdefghijk..
. хотя, безусловно, весь набранный алфавит гораздо чаще можно найти в Интернете, поиск ведется не по abcde *, а по изолированному abcde'contains'
, которое означает именно то, что я имею в виду во многих языках программирования. То же самое и'%searchTerm%'
с точки зрения SQL.Согласно документации Firestore , Cloud Firestore не поддерживает собственное индексирование или поиск текстовых полей в документах. Кроме того, загрузка всей коллекции для поиска полей на стороне клиента нецелесообразна.
Рекомендуются сторонние поисковые решения, такие как Algolia и Elastic Search .
источник
Несколько примечаний здесь:
1.)
\uf8ff
работает так же, как~
2.) Вы можете использовать предложение where или предложения start end:
точно так же, как
3.) Нет, это не сработает, если вы перевернете
startAt()
иendAt()
в каждой комбинации, однако вы можете добиться того же результата, создав второе поле поиска, которое перевернуто, и объединив результаты.Пример: сначала вы должны сохранить инвертированную версию поля при создании поля. Что-то вроде этого:
С его помощью вы можете искать последние буквы строкового поля и первые , а не случайные средние буквы или группы букв. Это ближе к желаемому результату. Однако это не особо поможет, когда нам нужны случайные средние буквы или слова. Кроме того, не забудьте сохранить все в нижнем регистре или копию в нижнем регистре для поиска, так что регистр не будет проблемой.
4.) Если у вас есть только несколько слов, метод Кена Тана сделает все, что вы хотите, или, по крайней мере, после того, как вы немного его измените. Однако, имея всего лишь абзац текста, вы в геометрической прогрессии создадите более 1 МБ данных, что больше, чем ограничение на размер документа firestore (я знаю, я это тестировал).
5.) Если бы вы могли комбинировать array-contains (или некоторую форму массивов) с
\uf8ff
уловкой, вы могли бы получить жизнеспособный поиск, который не достигнет пределов. Я пробовал каждую комбинацию, даже с картами, и ничего не вышло. Кто-нибудь это поймет, разместите здесь.6.) Если вам нужно уйти от АЛГОЛИИ и ЭЛАСТИЧЕСКОГО ПОИСКА, и я вас ни в чем не виню, вы всегда можете использовать mySQL, postSQL или neo4Js в Google Cloud. Их все 3 легко настроить, и у них есть бесплатные уровни. У вас будет одна облачная функция для сохранения данных onCreate () и другая функция onCall () для поиска данных. Просто ... иш. Почему бы тогда просто не перейти на mySQL? Конечно же, данные в реальном времени! Когда кто-то пишет DGraph с помощью websocks для данных в реальном времени, посчитайте меня!
Algolia и ElasticSearch созданы для работы с базами данных только для поиска, поэтому нет ничего более быстрого ... но вы платите за это. Google, почему вы уводите нас от Google, не следите за MongoDB noSQL и не разрешаете поиск?
ОБНОВЛЕНИЕ - Я СОЗДАЛ РЕШЕНИЕ:
https://fireblog.io/blog/post/firestore-full-text-search
источник
Поздний ответ, но для тех, кто все еще ищет ответ, скажем, у нас есть коллекция пользователей, и в каждом документе коллекции у нас есть поле «имя пользователя», поэтому, если вы хотите найти документ, в котором имя пользователя начинается с «al» мы можем сделать что-то вроде
источник
Я уверен, что Firebase скоро выпустит "string-contains" для захвата любого index [i] startAt в строке ... Но я исследовал сети и обнаружил, что это решение придумал кто-то другой, настроив ваши данные, например этот
запрос вроде этого
источник
Если вы не хотите использовать сторонний сервис, такой как Algolia, облачные функции Firebase - отличная альтернатива. Вы можете создать функцию, которая может получать входной параметр, обрабатывать записи на стороне сервера и затем возвращать те, которые соответствуют вашим критериям.
источник
Выбранный ответ работает только для точного поиска и не является естественным поведением пользователя при поиске (поиск «яблоко» в «Джо съел яблоко сегодня» не сработает).
Я думаю, что ответ Дэна Фейна выше следует поставить выше. Если данные String, которые вы ищете, короткие, вы можете сохранить все подстроки строки в массиве в своем документе, а затем выполнить поиск по массиву с помощью запроса Firebase array_contains. Документы Firebase ограничены 1 МиБ (1048576 байтов) ( квоты и ограничения Firebase ), что составляет около 1 миллиона символов, сохраненных в документе (я думаю, 1 символ ~ = 1 байт). Хранить подстроки можно, если ваш документ не приближается к отметке в 1 миллион.
Пример поиска по именам пользователей:
Шаг 1. Добавьте в проект следующее расширение String. Это позволяет легко разбить строку на подстроки. ( Я нашел это здесь ).
Шаг 2: Когда вы сохраняете имя пользователя, также сохраните результат этой функции в виде массива в том же документе. Это создает все варианты исходного текста и сохраняет их в массиве. Например, при вводе текста «Apple» будет создан следующий массив: [«a», «p», «p», «l», «e», «ap», «pp», «pl», «le "," app "," ppl "," ple "," app "," pple "," apple "], которые должны охватывать все критерии поиска, которые может ввести пользователь. Вы можете оставить maximumStringSize равным nil, если хотите получить все результаты, однако, если есть длинный текст, я бы рекомендовал ограничить его, прежде чем размер документа станет слишком большим - где-то около 15 мне подходит (большинство людей все равно не ищут длинные фразы ).
Шаг 3: вы можете использовать функцию array_contains Firebase!
источник
Я действительно думаю, что лучшее решение для этого в Firestore - это поместить все подстроки в массив и просто выполнить запрос array_contains. Это позволяет вам выполнять сопоставление подстрок. Немного избыточно хранить все подстроки, но если ваши условия поиска короткие, это очень разумно.
источник
У меня была эта проблема, и я нашел довольно простое решение.
IsGreaterThanOrEqualTo позволяет нам отфильтровать начало нашего поиска и, добавив «z» в конец isLessThanOrEqualTo, мы ограничиваем наш поиск, чтобы не переходить к следующим документам.
источник
С Firestore вы можете реализовать полнотекстовый поиск, но это все равно будет стоить больше операций чтения, чем было бы в противном случае, а также вам нужно будет вводить и индексировать данные определенным образом. Таким образом, в этом подходе вы можете использовать облачные функции firebase для tokenise, а затем хэшировать ваш входной текст, выбирая линейную хеш-функцию,
h(x)
которая удовлетворяет следующему - еслиx < y < z then h(x) < h (y) < h(z)
. Для токенизации вы можете выбрать несколько облегченных библиотек NLP, чтобы сократить время холодного запуска вашей функции, что может удалить ненужные слова из вашего предложения. Затем вы можете запустить запрос с операторами «меньше» и «больше» в Firestore. При сохранении ваших данных вам также необходимо убедиться, что вы хешируете текст перед его сохранением, и сохраните простой текст также, как если бы вы изменили простой текст, хешированное значение также изменится.источник
У меня это сработало отлично, но могло вызвать проблемы с производительностью.
Сделайте это при запросе firestore:
Сделайте это в своем FutureBuilder:
источник
На сегодняшний день существует в основном 3 различных обходных пути, которые были предложены экспертами в качестве ответов на вопрос.
Я перепробовал их все. Я подумал, что было бы полезно задокументировать свой опыт работы с каждым из них.
Метод A: Использование: (dbField "> =" searchString) & (dbField "<=" searchString + "\ uf8ff")
Предложено @Kuba и @Ankit Prajapati
A.1 Запросы Firestore могут выполнять фильтры диапазона (>, <,> =, <=) только для одного поля. Запросы с фильтрами диапазона для нескольких полей не поддерживаются. Используя этот метод, вы не можете иметь оператор диапазона в любом другом поле базы данных, например, поле даты.
А.2. Этот метод НЕ работает для поиска в нескольких полях одновременно. Например, вы не можете проверить, находится ли строка поиска в каком-либо из полей (имя, примечания и адрес).
Метод-B: использование MAP строк поиска с "true" для каждой записи на карте и использование оператора "==" в запросах.
Предложено @Gil Gilbert
B.1 Очевидно, этот метод требует дополнительной обработки каждый раз, когда данные сохраняются в базу данных, и, что более важно, требует дополнительного места для хранения карты строк поиска.
B.2 Если в запросе Firestore есть одно условие, подобное приведенному выше, то заранее создавать индекс не требуется. В этом случае это решение подойдет.
B.3 Однако, если запрос имеет другое условие, например (status === «active»,), кажется, что индекс требуется для каждой «строки поиска», которую вводит пользователь. Другими словами, если пользователь ищет «Джем», а другой пользователь ищет «Масло», необходимо заранее создать индекс для строки «Джем», а другой - для «Масло» и т. Д. Если вы не можете предсказать все возможные строки поиска пользователей, это НЕ работает - если в запросе есть другие условия!
** Метод-C: использование ARRAY строк поиска и оператора "array-contains".
Предложено @Albert Renshaw и продемонстрировано @Nick Carducci
C.1 Подобно методу-B, этот метод требует дополнительной обработки каждый раз, когда данные сохраняются в базу данных, и, что более важно, требует дополнительного места для хранения массива строк поиска.
C.2 Запросы Firestore могут включать не более одного предложения "array-contains" или "array-contains-any" в составном запросе.
Общие ограничения:
Не существует универсального решения. У каждого обходного пути есть свои ограничения. Я надеюсь, что приведенная выше информация поможет вам в процессе выбора между этими обходными путями.
Список условий запроса Firestore см. В документации https://firebase.google.com/docs/firestore/query-data/queries .
Я не пробовал https://fireblog.io/blog/post/firestore-full-text-search , который предлагает @Jonathan.
источник
Мы можем использовать обратную галочку, чтобы распечатать значение строки. Это должно работать:
источник