Google DataStore with objectify - HashMap 上的复合查询
Google DataStore with objectify - composite queries on HashMap
我正在使用 Google App Engine 作为我的 REST 服务后端,Google dataStore 作为 DB 和 objectify 来访问数据存储。
我的实体中的属性之一是
Map<String,String> customAttrs;
这是因为我事先不知道客户端可以提供哪些参数。我的要求是我希望能够在 HashMap 中对这些参数进行索引。
我看了下面的问题:
GAE w/ Objectify - Can you query a HashMap?
并尝试了接受的答案中提到的内容,它对我有用,我可以使用
根据 customAttrs 中的属性进行索引
filter("customAttrs .key1", "value1")
基于客户端在 REST API 调用中传递的任何查询参数。
但是,问题出现在复合查询的情况下。我对此了解不多,但据我了解,如果将排序或不等式过滤器与另一个过滤器结合使用,则必须在名为的文件中定义组合
数据存储-indexes.xml。因此,实体中的一个字段是 creationTime,当我执行任何查询 returns 我的用户列表时,我想按 creationTime 对其进行排序。
假设地图 customAttrs 中的一个键是 city。现在,如果我只想过滤 city=London 所在的所有用户,它对我来说效果很好。但是,如果我尝试让 city=London 的所有用户按 creationTime 排序,它 returns 是一个异常并且不起作用。仅当我在文件 datastore-indexes.xml:
中添加以下内容时它才有效
<datastore-index kind="User" ancestor="false" source="manual">
<property name="customAttrs.city" direction="asc" />
<property name="creationTime" direction="asc" />
</datastore-index>
现在这会破坏使用 HashMap 的目的,因为在这里我需要事先知道 customAttrs 中的字段。
那么有什么方法可以执行复合查询而无需事先知道字段?
编辑:
正如 Sai 在回答中提到的那样,如果不事先添加并添加到数据存储中,就无法执行这些类型的查询-indexes.xml。
我想到了另一种方法,但我遇到了不同的问题。
在这种方法中,不是将 属性 定义为
Map<String,String> customAttrs;
我把它定义为一个字符串列表
List<String> customAttrs;
此处存储的字符串的形式为"key:value"。例如,实体的列表可能是 "city:abc"、"country:xyz"、"name:123"
在这种情况下,我只需要在我的 数据存储中定义以下内容-indexes.xml:
<datastore-index kind="User" ancestor="false" source="manual">
<property name="customAttrs" direction="asc" />
<property name="creationTime" direction="asc" />
</datastore-index>
这对我来说很好,因为我无处可去 hard-coding/pre-defining 可能是什么属性。我可以使用
按 city=abc 进行过滤
filter("customAttrs","city:abc")
通过这种方法,我可以按任何一个参数进行过滤,并按创建时间对结果进行排序。
但是这种方法的问题是我只能做一种类型的自定义过滤器。
这意味着如果我想过滤城市是 abc 而国家是 xyz 的地方(如果我使用 Map 方法就可以),我无法做到。有什么办法吗。
所以基本上我的查询是,如果一个实体有一个 属性 列表,有没有办法过滤所有那些在列表中有字符串 "str1" 和 "str2" 的实体?
这与 Objectfy 无关,而是 Datastore 本身。每当您的查询搜索多个属性或像您提到的那样进行排序(搜索和排序两个不同的属性)时,数据存储都需要一个匹配的复合索引。 Datastore 旨在让所有查询都从单个索引获取结果以提高性能。也就是说,如果您允许提前不知道其名称的动态属性,那么实际上没有办法像您想要的那样执行查询。如果这是一个选项,您的应用程序应该限制这些动态属性的 querying/sorting,这样它们就不需要复合索引。否则,您将不得不探索替代选项,例如全文搜索(AppEngine 的全文搜索或 Elastic 搜索),看看它们是否对您的用例有所帮助。
关于过滤数组属性的最新问题 -
可以对数组类型执行 AND
查询以查看它是否包含两个或更多元素。 GQL 希望 -
SELECT * FROM MyEntity WHERE ArrayProperty='value1' AND ArrayProperty='value2'
我正在使用 Google App Engine 作为我的 REST 服务后端,Google dataStore 作为 DB 和 objectify 来访问数据存储。 我的实体中的属性之一是
Map<String,String> customAttrs;
这是因为我事先不知道客户端可以提供哪些参数。我的要求是我希望能够在 HashMap 中对这些参数进行索引。 我看了下面的问题:
GAE w/ Objectify - Can you query a HashMap?
并尝试了接受的答案中提到的内容,它对我有用,我可以使用
根据 customAttrs 中的属性进行索引filter("customAttrs .key1", "value1")
基于客户端在 REST API 调用中传递的任何查询参数。
但是,问题出现在复合查询的情况下。我对此了解不多,但据我了解,如果将排序或不等式过滤器与另一个过滤器结合使用,则必须在名为的文件中定义组合 数据存储-indexes.xml。因此,实体中的一个字段是 creationTime,当我执行任何查询 returns 我的用户列表时,我想按 creationTime 对其进行排序。
假设地图 customAttrs 中的一个键是 city。现在,如果我只想过滤 city=London 所在的所有用户,它对我来说效果很好。但是,如果我尝试让 city=London 的所有用户按 creationTime 排序,它 returns 是一个异常并且不起作用。仅当我在文件 datastore-indexes.xml:
中添加以下内容时它才有效<datastore-index kind="User" ancestor="false" source="manual">
<property name="customAttrs.city" direction="asc" />
<property name="creationTime" direction="asc" />
</datastore-index>
现在这会破坏使用 HashMap 的目的,因为在这里我需要事先知道 customAttrs 中的字段。
那么有什么方法可以执行复合查询而无需事先知道字段?
编辑:
正如 Sai 在回答中提到的那样,如果不事先添加并添加到数据存储中,就无法执行这些类型的查询-indexes.xml。
我想到了另一种方法,但我遇到了不同的问题。
在这种方法中,不是将 属性 定义为
Map<String,String> customAttrs;
我把它定义为一个字符串列表
List<String> customAttrs;
此处存储的字符串的形式为"key:value"。例如,实体的列表可能是 "city:abc"、"country:xyz"、"name:123"
在这种情况下,我只需要在我的 数据存储中定义以下内容-indexes.xml:
<datastore-index kind="User" ancestor="false" source="manual">
<property name="customAttrs" direction="asc" />
<property name="creationTime" direction="asc" />
</datastore-index>
这对我来说很好,因为我无处可去 hard-coding/pre-defining 可能是什么属性。我可以使用
按 city=abc 进行过滤filter("customAttrs","city:abc")
通过这种方法,我可以按任何一个参数进行过滤,并按创建时间对结果进行排序。
但是这种方法的问题是我只能做一种类型的自定义过滤器。 这意味着如果我想过滤城市是 abc 而国家是 xyz 的地方(如果我使用 Map 方法就可以),我无法做到。有什么办法吗。 所以基本上我的查询是,如果一个实体有一个 属性 列表,有没有办法过滤所有那些在列表中有字符串 "str1" 和 "str2" 的实体?
这与 Objectfy 无关,而是 Datastore 本身。每当您的查询搜索多个属性或像您提到的那样进行排序(搜索和排序两个不同的属性)时,数据存储都需要一个匹配的复合索引。 Datastore 旨在让所有查询都从单个索引获取结果以提高性能。也就是说,如果您允许提前不知道其名称的动态属性,那么实际上没有办法像您想要的那样执行查询。如果这是一个选项,您的应用程序应该限制这些动态属性的 querying/sorting,这样它们就不需要复合索引。否则,您将不得不探索替代选项,例如全文搜索(AppEngine 的全文搜索或 Elastic 搜索),看看它们是否对您的用例有所帮助。
关于过滤数组属性的最新问题 -
可以对数组类型执行 AND
查询以查看它是否包含两个或更多元素。 GQL 希望 -
SELECT * FROM MyEntity WHERE ArrayProperty='value1' AND ArrayProperty='value2'