我有一个数据存储区,其中一个属性包含一个字符串数组。每个实体可以具有该阵列的不同大小。我想进行查询并过滤每个实体中数组的内容。
我目前生成一组过滤器,一个用于数组中每个必需的字符串。然后,我构建一个在EntityQuery中使用的复合过滤器。过滤器的生成如下:
// arrayProperty is the name on the property in my Datastore that contains the array of strings.
List<PropertyFilter> pathFilters = Arrays.stream(new String[] {"a","b","c"})
.map(s -> PropertyFilter.eq("arrayProperty", s))
.collect(Collectors.toList());
然而,这将使用arrayProperty = [a,b,c]和arrayProperty = [a,b,c,d]匹配两个实体。
我是否可以在com.google.cloud.datastore中使用来自JAVA库的Google Cloud Datastore查询来过滤掉属性值为具有完全相同元素的特定数组的实体(不多,不少且与订单无关)?也许通过某种大小的过滤器或完全不同的查询/过滤器。或者我可以使用GQL吗?
答案 0 :(得分:1)
您不能对Array属性执行相等过滤(或完全匹配)。您只能查询包含一个或多个单独元素的实体。根据您的示例数据([a, b, c]
和[a, b, c, d]
),可以进行以下查询:
arrayProperty="a"
- 返回两个实体arrayProperty="a" AND arrayProperty="b"
- 返回两个实体arrayProperty="a" AND arrayProperty="b" AND arrayProperty="c"
- 返回两个实体arrayProperty="a" AND arrayProperty="b" AND arrayProperty="c" AND arrayProperty="d"
- 只返回一个实体arrayProperty='x'
- 两者都不匹配您可以期望Query / Filter和GQL具有相同的行为。
一个解决方法是将Array属性中的元素数存储在单独的字段中,然后在Count属性和Array属性上创建复合索引。然后你的查询可能是这样的:
WHERE count=3 AND arrayProperty="a" AND arrayProperty="b" AND arrayProperty="c"
这将返回其arrayProperty正好具有3个元素且arrayProperty以任何顺序具有a,b和c的所有实体。
您还必须确保在创建/更新实体时新的计数属性保持同步。
虽然这应该会产生预期的结果,但您的索引大小会更多。
您也可以选择将计数转储到原始数组字段(作为整数),假设您的数组中的主数据是String类型。使用此方法,您可以避免使用复合索引。