我有一个包含以下字段的索引实体:
@Index private String entry;
@Index private Date created;
// ...
查询索引时,将搜索词的首字母(此处为:find)与条目进行比较:
Key<Result> fromKey = Key.create(Result.class, find);
Key<Result> toKey = Key.create(Result.class, find + "\uFFFD");
query = query.filterKey(">=", fromKey).filterKey("<", toKey);
[请注意,在这种情况下,条目被附加并用作键,但在这方面不应改变任何内容。]
这将返回条目以搜索词开头的所有实体。到目前为止,很好。
现在我希望结果按“创建”日期排序,但应用商店不允许我这样做:
query = query.order("-created");
它返回“java.lang.IllegalArgumentException:第一个排序属性必须与应用不等式过滤器的属性相同。”
我无法在代码中进行排序,因为我需要进行分页,我总是根据“创建”日期查询下一页结果:客户端查询第一页,然后发送相同的查询日期最后结果接收到第二页等
从本质上讲,我认为问题归结为我们这里涉及两个不等式过滤器,而数据存储不支持。
有没有办法有效地解决这个问题?你怎么写索引?您改用全文搜索吗?或者有没有办法在 datastore/objectify 中解决这个问题,比如使用多个字段的复合索引来规避这个问题?
--
我想出的唯一奇怪的解决方案是在索引记录中创建多个字段或多次添加记录。示例:
entry = "hotel"-> 添加为 "h"、"ho"、"hot"、"hote"和 "hotel"
不是很有效,但这会使不等式搜索成为等式搜索。
最佳答案
我使用一个索引的多属性字段来实现“按类型搜索”,该字段填充了“命中”的每个片段,类似于您的“奇怪的解决方案”。搜索查询是一个等式过滤器,加上另一个字段上的不等式过滤器以进行排序。这有利于满足此处描述的“高级索引”查询:
https://developers.google.com/appengine/articles/indexselection
...因此,如果用户输入多个片段,您可以对该字段进行多次过滤。
等式查询非常高效;唯一的缺点是额外的存储和索引。这是否是一个问题取决于您存储的行数和片段数(以及您的预算)。
FWIW,所有基于 Lucene 的文本搜索引擎(Elasticsearch、Solr 等)的工作方式都差不多——它们索引从分析的 token 到文档的反向映射。事实上,您可以有效地使用 Lucene 分析器来创建索引片段。只需确保分析查询词以及存储的数据即可。
关于java - 如何在 objectify 中编写索引,首先返回最新的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25872497/