【问题标题】:How to write an index in objectify, which returns the newest results first?如何在objectify中编写一个索引,它首先返回最新的结果?
【发布时间】:2014-09-16 15:15:09
【问题描述】:

我有一个包含以下字段的索引实体:

@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:第一个排序属性必须与应用不等式过滤器的属性相同。”

我无法在代码中进行排序,因为我需要进行分页,我总是根据“创建”日期查询下一页结果:客户端查询第一页,然后发送带有日期的相同查询接收第二页的最后一个结果,等等。

从本质上讲,我认为问题在于我们这里涉及到两个不等式过滤器,而数据存储区不支持。

有没有办法有效地解决这个问题?如何编写索引?您是否改用全文搜索?或者有没有办法在数据存储/对象化中解决这个问题,比如使用多个字段的复合索引来规避这个问题?

--

我想出的唯一奇怪的解决方案是在索引记录中创建多个字段或多次添加记录。示例:

entry = "hotel" -> 添加为 "h"、"ho"、"hot"、"hote" 和 "hotel"

效率不是很高,但这会使不等式搜索成为等式搜索。

【问题讨论】:

    标签: java google-app-engine google-cloud-datastore objectify


    【解决方案1】:

    我使用一个索引多属性字段填充了“命中”的每个片段,类似于您的“奇怪的解决方案”,我实现了“即键入即搜索”。搜索查询是一个等式过滤器,加上另一个字段上的一个不等式过滤器,用于排序。这有利于满足此处描述的“高级索引”查询:

    https://developers.google.com/appengine/articles/indexselection

    ...因此,如果用户键入多个片段,您可以多次过滤该字段。

    相等查询非常有效;唯一的缺点是额外的存储和索引。这是否是一个问题取决于您存储的行数和片段数(以及您的预算)。

    FWIW,所有基于 Lucene 的文本搜索引擎(Elasticsearch、Solr 等)的工作方式都差不多——它们索引从分析的令牌到文档的反向映射。事实上,您可以有效地使用 Lucene 分析器来创建索引片段。只需确保分析查询词以及存储的数据即可。

    【讨论】:

    • 多属性字段比使用多个字段更智能我猜[我不知道这存在],但我假设索引仍将每个值存储为单独的项目。如何在 objectify 中设置多属性字段?只需将 Google 描述的集合用于本机数据存储?
    • @Index 私有列表 条目;条目 = 新的 ArrayList(); entry.add(entry.substring(0, 3)); entry.add(entry.substring(0, 4)); entry.add(entry.substring(0, 6)); entry.add(entry.substring(0, 9));未格式化,抱歉,但这行得通吗?
    • 索引多属性字段是解决方案。效果很好,谢谢!
    【解决方案2】:

    不幸的是,我在 google 的一个 IO 中看到解释数据存储区(如果我能记住哪个-_-),由于数据是如何为查询建立索引的,它们迫使您使用不等式过滤器作为您的第一个排序顺序。以另一种方式使用它会强制执行服务器端计算,这是数据存储无法做到的。

    在这些情况下,我通常会在应用程序本身内进行排序,正如您所指出的,这不是您的解决方案。因此,要么对不同的日期使用不同的表格并仅查询“正确的表格”,要么在搜索字符串时使用“hack”,这将是我能想到的绕过您的问题的唯一可行方法。如果有别的想法,我会编辑这个,但到目前为止我没有看到任何其他方式。

    【讨论】:

      猜你喜欢
      • 2013-06-29
      • 2012-04-23
      • 1970-01-01
      • 2013-11-19
      • 1970-01-01
      • 1970-01-01
      • 2018-03-13
      • 2022-07-19
      • 2020-08-28
      相关资源
      最近更新 更多