Firestore同时做BookTitle范围查询和UserID字段存在性过滤如何实现
问题原因
Firestore 内置查询规则限制:所有涉及不等式的过滤条件(notEqualTo、notIn、<、<=、>、>=、范围查询)必须作用在同一个字段上。你原来的查询对BookTitle做了范围查询(属于不等式类过滤),新增的whereNotEqualTo("UserID", null)也是不等式过滤,两个条件作用在不同字段,因此触发报错。
可行解决方案
下面两种方案都可以避免客户端过滤浪费读操作额度的问题:
方案1:新增标记字段做等式过滤
给所有Books集合的文档新增HasUserID布尔类型字段:
- 有UserID字段的文档,
HasUserID设为true - 无UserID字段的公开书籍文档,
HasUserID设为false
因为等式过滤可以和其他字段的不等式过滤共存,调整后的查询语句如下:
db.collection( "Books" ) .whereEqualTo("HasUserID", false) .whereGreaterThanOrEqualTo( "BookTitle", s.toString() ) .whereLessThanOrEqualTo( "BookTitle", s.toString() + "\uF7FF" ) .limit( 5 ) .get() .addOnCompleteListener( task -> { if (task.isSuccessful()) { for (QueryDocumentSnapshot document : task.getResult()) { // 业务逻辑处理 } } } );
首次运行查询时如果提示缺少复合索引,点击报错日志中的索引创建链接,等待索引生成后即可正常使用。
方案2:给无UserID的文档设置默认值
不需要新增字段,直接给所有原本没有UserID字段的文档,批量更新UserID字段为固定的特殊默认值,比如"PUBLIC_BOOK",之后用等式过滤即可:
db.collection( "Books" ) .whereEqualTo("UserID", "PUBLIC_BOOK") .whereGreaterThanOrEqualTo( "BookTitle", s.toString() ) .whereLessThanOrEqualTo( "BookTitle", s.toString() + "\uF7FF" ) .limit( 5 ) .get() .addOnCompleteListener( task -> { if (task.isSuccessful()) { for (QueryDocumentSnapshot document : task.getResult()) { // 业务逻辑处理 } } } );
这个方案不需要修改字段结构,只需要做一次旧数据批量更新即可,后续新增公开书籍时直接把UserID设为默认值就行。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

