간단한 검색 필드를 추가하고 싶습니다. 다음과 같은 것을 사용하고 싶습니다.
collectionRef.where('name', 'contains', 'searchTerm')
을 사용해 보았지만 where('name', '==', '%searchTerm%')
아무것도 반환하지 않았습니다.
답변
그런 운영자가 없다, 허용 사람은 ==
, <
, <=
, >
, >=
.
당신은 사이의 시작이 그 모든 것을 예를 들어, 단지 접두사에 의해 필터링 할 수 있습니다 bar
및 foo
사용할 수있는
collectionRef.where('name', '>=', 'bar').where('name', '<=', 'foo')
이를 위해 Algolia 또는 ElasticSearch 와 같은 외부 서비스를 사용할 수 있습니다 .
답변
제한이 진행되는 한 Kuba의 대답은 사실이지만 세트와 같은 구조로 부분적으로 에뮬레이션 할 수 있습니다.
{
'terms': {
'reebok': true,
'mens': true,
'tennis': true,
'racket': true
}
}
이제 다음으로 쿼리 할 수 있습니다.
collectionRef.where('terms.tennis', '==', true)
이는 Firestore가 모든 필드에 대해 자동으로 색인을 생성하기 때문에 작동합니다. 불행히도 Firestore는 복합 색인을 자동으로 생성하지 않기 때문에 복합 쿼리에 대해 직접 작동하지 않습니다.
단어 조합을 저장하여이 문제를 해결할 수 있지만 속도가 너무 빠릅니다.
여전히 아웃 보드 전체 텍스트 검색을 사용하는 것이 좋습니다 .
답변
@Kuba의 답변에 동의하지만 접두사 검색에 완벽하게 작동하려면 작은 변경 사항을 추가해야합니다. 여기 나를 위해 일한 것
이름으로 시작하는 레코드 검색 queryText
collectionRef.where('name', '>=', queryText).where('name', '<=', queryText+ '\uf8ff')
.
\uf8ff
쿼리에 사용 된 문자 는 유니 코드 범위에서 매우 높은 코드 포인트입니다 (PUA (Private Usage Area) 코드). 유니 코드에서 대부분의 일반 문자 뒤에 있기 때문에 쿼리는로 시작하는 모든 값과 일치합니다 queryText
.
답변
Firebase는 문자열 내에서 용어 검색을 명시 적으로 지원하지 않지만
Firebase는 (현재) 귀하의 사례와 다른 많은 문제를 해결할 다음을 지원합니다.
2018 년 8 월부터 array-contains
쿼리 를 지원 합니다. 참조 : https://firebase.googleblog.com/2018/08/better-arrays-in-cloud-firestore.html
이제 모든 주요 용어를 필드로 배열에 설정 한 다음 ‘X’가 포함 된 배열이있는 모든 문서를 쿼리 할 수 있습니다. 논리 AND를 사용하여 추가 쿼리에 대한 추가 비교를 수행 할 수 있습니다. (Firebase 는 현재 여러 배열 포함 쿼리에 대한 복합 쿼리를 기본적으로 지원하지 않기 때문입니다. ‘AND’정렬 쿼리는 클라이언트 측에서 수행해야합니다.)
이 스타일로 배열을 사용하면 동시 쓰기에 최적화 될 수 있습니다. 일괄 요청을 지원하는지 테스트하지 않았지만 (문서는 말하지 않음) 공식 솔루션이기 때문에 그렇게 할 것입니다.
용법:
collection("collectionPath").
where("searchTermsArray", "array-contains", "term").get()
답변
당 경우 FireStore 워드 프로세서 , 클라우드 경우 FireStore은 기본 인덱싱을 지원하지 않거나 문서에서 텍스트 필드를 검색합니다. 또한 클라이언트 측에서 필드를 검색하기 위해 전체 컬렉션을 다운로드하는 것은 실용적이지 않습니다.
Algolia 및 Elastic Search 와 같은 타사 검색 솔루션 이 권장됩니다.
답변
여기에 몇 가지 참고 사항 :
1.) \uf8ff
다음과 같은 방식으로 작동합니다.~
2.) where 절 또는 start end 절을 사용할 수 있습니다.
ref.orderBy('title').startAt(term).endAt(term + '~');
정확히 동일
ref.where('title', '>=', term).where('title', '<=', term + '~');
3) 당신이 반대하면 아니, 그것은 작동하지 않습니다 startAt()
및 endAt()
모든 조합에서, 그러나, 당신이 반전되는 제 2 검색 필드를 생성하고, 그 결과를 조합하여 동일한 결과를 얻을 수 있습니다.
예 : 먼저 필드를 만들 때 필드의 반전 된 버전을 저장해야합니다. 이 같은:
// collection
const postRef = db.collection('posts')
async function searchTitle(term) {
// reverse term
const termR = term.split("").reverse().join("");
// define queries
const titles = postRef.orderBy('title').startAt(term).endAt(term + '~').get();
const titlesR = postRef.orderBy('titleRev').startAt(termR).endAt(termR + '~').get();
// get queries
const [titleSnap, titlesRSnap] = await Promise.all([
titles,
titlesR
]);
return (titleSnap.docs).concat(titlesRSnap.docs);
}
이것으로, 당신은 마지막을 검색 할 수 있습니다 임의의 중간 문자 나 문자 그룹이 아닌 문자열 필드 문자와 첫 번째 문자를 . 이것은 원하는 결과에 더 가깝습니다. 그러나 이것은 우리가 임의의 중간 문자 나 단어를 원할 때 실제로 도움이되지 않습니다. 또한 모든 것을 소문자로 저장하거나 검색을 위해 소문자 사본을 저장해야하므로 대소 문자가 문제가되지 않습니다.
4.) 단어가 몇 개 밖에없는 경우 Ken Tan의 방법 은 원하는 모든 것을 수행하거나 최소한 약간 수정 한 후에 수행합니다. 그러나 텍스트 단락만으로도 1MB 이상의 데이터를 기하 급수적으로 생성 할 수 있으며 이는 firestore의 문서 크기 제한보다 큽니다 (알고 있습니다. 테스트했습니다).
5.) 배열 포함을 결합 할 수있는 경우 (또는 배열의 일부 형태)을 \uf8ff
트릭 과 한계에 도달하지 않는 실행 가능한 검색이있을 수 있습니다. 나는지도와 함께 모든 조합을 시도했고, 가도 안된다. 누구나 이것을 알아 내고 여기에 게시하십시오.
6.) ALGOLIA 및 ELASTIC SEARCH에서 벗어나야하고 내가 당신을 탓하지 않는다면 Google Cloud에서 항상 mySQL, postSQL 또는 neo4J를 사용할 수 있습니다. 세 가지 모두 설정이 쉬우 며 프리 티어가 있습니다. 데이터를 저장하는 클라우드 함수 onCreate ()와 데이터 검색을위한 onCall () 함수가 있습니다. 단순하다 … 그렇다면 mySQL로 전환하지 않는 이유는 무엇입니까? 물론 실시간 데이터! 누군가 가 실시간 데이터를 위해 websocks 로 DGraph를 작성하면 저를 세어보세요!
Algolia와 ElasticSearch는 검색 전용 db로 구축되었으므로 빠르지는 않지만 비용을 지불하면됩니다. Google, 왜 우리를 Google에서 멀어지게하고 MongoDB noSQL을 따르고 검색을 허용하지 않습니까?
업데이트-솔루션을 만들었습니다.
답변
늦은 답변이지만 여전히 답변을 찾고있는 모든 사용자를 위해 사용자 컬렉션이 있고 컬렉션의 각 문서에 “username”필드가 있으므로 사용자 이름이 “al”로 시작하는 문서를 찾고 싶다면 우리는 다음과 같이 할 수 있습니다
FirebaseFirestore.getInstance().collection("users").whereGreaterThanOrEqualTo("username", "al")