按列表过滤 - Objectify

时间:2012-10-18 07:35:56

标签: java google-app-engine objectify

此查询有效,fullPath字段为List<String>

    KeyLookup lookup 
        = ofy().load().type(KeyLookup.class).filter("fullPath IN", key.getFullPath()).first().get();

上面的查询还会获取String中与List<String>具有相同key.getFullPath()个元素的实体,但是它还会获取列表中具有相同字符串的实体以及其他< strong>更多列表中的字符串。

如何仅过滤列表中具有完全相同元素的实体,例如“不多,不少”

更新

例如

一个实体(比如Object1)字段fullPath包含:

  • “一”
  • “两个”
  • “三”

另一个实体(比如Object2)字段fullPath包含:

  • “一”
  • “两个”
  • “三”
  • “四”

key.getFullPath包含:

  • “一”
  • “两个”
  • “三”
  • “四”

然后上面的查询将返回Object1Object2,但我需要的是它只返回Object2

2 个答案:

答案 0 :(得分:3)

假设您想要完全匹配(没有更多值,没有更少的值),则没有“本机数据存储”方式来实现它。 IN为您提供操作,多次调用filter()会为您提供操作 - 两者都不是完全匹配。但是,有办法。

选项1:将列表加入单个索引属性

将列表中的所有项连接成单个值,并将其存储为合成索引属性。也许您需要根据订单或案例的重要性对其进行标准化。查询该属性,而不是列表属性。

只有在连续值保证低于500个字符时才能使用。似乎不太可能。相反,你可能想要......

选项2:对列表的哈希进行索引和查询

  1. 创建一个合成属性,其中包含所有列表值的哈希值,例如fullPathHash。它不需要加密安全; MD5很好。
  2. 每当更新list属性时,请更新哈希。
  3. 索引fullPathHash;你不需要索引列表属性。
  4. 当您查询项目列表时,查询哈希值。由于可能存在冲突,请进行查询后检查以确保列表相同并跳过任何误报。

答案 1 :(得分:1)

这是预期的,因为在比较查询中的两个列表时,实际发生的事情是数据存储区为筛选器列表中的每个值触发多个查询。因此,当您查询Object2时,会对Object2中的每个值执行四个查询。由于Object1Object2的“子集”,因此它也与查询匹配。这是您同时获得Object1Object2的原因。

您可以修改查询以使用AND运算符以强制完全匹配。所以,您可以拥有以下内容:

Query<KeyLookup> q = ofy().load().type(KeyLookup.class);
for (String f : key.getFullPath()) {
    q = q.filter("fullPath", f);
}
KeyLookup lookup = q.first().get();

希望这会有所帮助。