在集合 collectionGroup 查询中搜索
Searching within collection collectionGroup query
所以我遇到了这个允许将 collectionGroup 查询限制为特定文档的答案:CollectionGroupQuery but limit search to subcollections under a particular document
但是我还想使用 where
根据特定字段进一步过滤结果,这需要索引。查询没有错误,但它总是 returns 空快照:
const cityRef = firebase.firestore().doc('cities/cityId');
firebase.firestore().collectionGroup('attractions')
.where('name', '>=', keywords),
.where('name', '<=', keywords + '\uf8ff')
.orderBy('name')
.orderBy(firebase.firestore.FieldPath.documentId())
.startAt(cityRef.path),
.endAt(cityRef.path + "\uf8ff")
.get()
.then((querySnapshot) => {
console.log("Found " + querySnapshot.size + " docs");
querySnapshot.forEach((doc) => console.log("> " + doc.ref.path))
})
.catch((err) => {
console.error("Failed to execute query", err);
})
firebaser 在这里
问题几乎可以肯定是您的查询对两个不同的字段(name
和文档路径)进行了范围检查,这在 Firestore 的查询模型中是不可能的。作为 query limitations says 上的文档:
In a compound query, range (<, <=, >, >=) and not equals (!=, not-in) comparisons must all filter on the same field.
就此限制而言,您的 startAt
和 endAt
子句只是 >
和 <
的不同写法。
要了解为什么 SDK 允许您编写此查询,但没有给您想要的结果,我们必须更深入地研究它,所以...
是可能的,是将所有相关字段传递给startAt
和endAt
,以便它可以确定所有这些字段值的正确切片.
这样做也将消除 where
的需要,所以它是:
firebase.firestore().collectionGroup('attractions')
.orderBy('name')
.orderBy(firebase.firestore.FieldPath.documentId())
.startAt(keywords, cityRef.path),
.endAt(keywords + '\uf8ff', cityRef.path + "\uf8ff")
.get()
...
但此查询现在首先查找从 keywords
开始的文档,然后在必要时查找 cityRef.path
以消除多个结果之间的歧义。
你想要的是这个查询的等价物:
const docId = firebase.firestore.FieldPath.documentId()l
firebase.firestore().collectionGroup('attractions')
.orderBy('name')
.where('name', '>=', keywords),
.where('name', '<=', keywords + '\uf8ff')
.orderBy(firebase.firestore.FieldPath.documentId())
.where(docId, '>=', cityRef.path),
.where(docId, '<=', cityRef.path + '\uf8ff')
现在很清楚为什么这是不可能的,因为我们有两个字段的范围条件。
我一直试图让它在这个 jsbin (https://jsbin.com/yiyifin/edit?js,console) 中工作,到目前为止没有成功,但如果我让它工作或有最终裁决,我会 post 回来为什么它不起作用。
所以我遇到了这个允许将 collectionGroup 查询限制为特定文档的答案:CollectionGroupQuery but limit search to subcollections under a particular document
但是我还想使用 where
根据特定字段进一步过滤结果,这需要索引。查询没有错误,但它总是 returns 空快照:
const cityRef = firebase.firestore().doc('cities/cityId');
firebase.firestore().collectionGroup('attractions')
.where('name', '>=', keywords),
.where('name', '<=', keywords + '\uf8ff')
.orderBy('name')
.orderBy(firebase.firestore.FieldPath.documentId())
.startAt(cityRef.path),
.endAt(cityRef.path + "\uf8ff")
.get()
.then((querySnapshot) => {
console.log("Found " + querySnapshot.size + " docs");
querySnapshot.forEach((doc) => console.log("> " + doc.ref.path))
})
.catch((err) => {
console.error("Failed to execute query", err);
})
firebaser 在这里
问题几乎可以肯定是您的查询对两个不同的字段(name
和文档路径)进行了范围检查,这在 Firestore 的查询模型中是不可能的。作为 query limitations says 上的文档:
In a compound query, range (<, <=, >, >=) and not equals (!=, not-in) comparisons must all filter on the same field.
就此限制而言,您的 startAt
和 endAt
子句只是 >
和 <
的不同写法。
要了解为什么 SDK 允许您编写此查询,但没有给您想要的结果,我们必须更深入地研究它,所以...
是可能的,是将所有相关字段传递给startAt
和endAt
,以便它可以确定所有这些字段值的正确切片.
这样做也将消除 where
的需要,所以它是:
firebase.firestore().collectionGroup('attractions')
.orderBy('name')
.orderBy(firebase.firestore.FieldPath.documentId())
.startAt(keywords, cityRef.path),
.endAt(keywords + '\uf8ff', cityRef.path + "\uf8ff")
.get()
...
但此查询现在首先查找从 keywords
开始的文档,然后在必要时查找 cityRef.path
以消除多个结果之间的歧义。
你想要的是这个查询的等价物:
const docId = firebase.firestore.FieldPath.documentId()l
firebase.firestore().collectionGroup('attractions')
.orderBy('name')
.where('name', '>=', keywords),
.where('name', '<=', keywords + '\uf8ff')
.orderBy(firebase.firestore.FieldPath.documentId())
.where(docId, '>=', cityRef.path),
.where(docId, '<=', cityRef.path + '\uf8ff')
现在很清楚为什么这是不可能的,因为我们有两个字段的范围条件。
我一直试图让它在这个 jsbin (https://jsbin.com/yiyifin/edit?js,console) 中工作,到目前为止没有成功,但如果我让它工作或有最终裁决,我会 post 回来为什么它不起作用。