有两种实体:User和Trip。用户是旅行的父母,旅行是用户的子女。Google App Engine数据存储:如果父密钥未知,如何通过ID /名称获取实体?
为了保护隐私,我仅发布旅程ID /姓名。因为它看起来像一个Trip Key包含编码的用户ID /名称。
如何通过ID /名称获取实体(如果父密钥未知?
有两种实体:User和Trip。用户是旅行的父母,旅行是用户的子女。Google App Engine数据存储:如果父密钥未知,如何通过ID /名称获取实体?
为了保护隐私,我仅发布旅程ID /姓名。因为它看起来像一个Trip Key包含编码的用户ID /名称。
如何通过ID /名称获取实体(如果父密钥未知?
你不能。父键是实体键的一部分,你需要一个完整的键来获得一个实体。
此外,query with key filter将不会找到具有父母的实体,除非您指定祖先密钥。
@ peter-knego第一个问题:用户是Trip的父母。要通过id获取实体,您需要使用父级重建密钥来获取完整密钥。但是,您可以避免这种情况,只需为Trip的全部密钥分配ID。你可以用分配的ID构造完整的密钥。这是我的逻辑。
如果您在“根”实体下创建所有“用户”实体,并将“uuid”属性添加到“Trip”实体,则可以使用指定的UUID查找单个“Trip”。
Filter uuidFilter = new FilterPredicate("uuid", FilterOperator.EQUAL, uuid.toString());
Query q = new Query("Trip").setAncestor(root.getKey()).setFilter(uuidFilter);
你可以做这样的事情:
public Entity GetEntity(String kind, String idName)
throws EntityNotFoundException{
Key key = KeyFactory.createKey(kind, Long.parseLong(idName));
return datastore.get(key);
}
不,它不会找到任何东西,除非你在'key'中指定父项。 –
我工作了3个替代品可以解决这个问题,这是一个非常重要的恕我直言。
----第一备选物----
如果你旅行的ID从其他属性计算,有一种方法。而不是通过其id
得到Trip
从其他计算属性中获取它。让我们想象你的Trip的id是用一些规范的名字来计算的(例如你可以从它的完整标题中推断出一个URN),例如如果旅行的全名是
航程珠峰
您的规范名称可能是voyage-to-the-everest
,这是你作为名称使用的密钥字符串。因此,而不是使用datastore.get
使用获得的元素:
@Override
public Optional<Trip> findById(String tripCanonicalName) {
StructuredQuery.PropertyFilter eqTripCanonicalName = StructuredQuery.PropertyFilter
.eq("canonicalName", tripCanonicalName);
EntityQuery query = Query.newEntityQueryBuilder().setKind("Trip")
.setFilter(eqTripCanonicalName).setLimit(1).build();
QueryResults<Entity> results = getDatastoreService().run(query);
if (results.hasNext()) {
return Optional.of(fromEntity(results.next()));
}
return Optional.empty();
}
这将让实体(Trip
)不管其父母(User
)是。
----第二个替代----
之前访问的元素可能是你首先要列出它们,然后选择一个,去接入链路。因为我们知道使用任务的ID不会足够,因为这将是只为其父(User
)独特的,但不是表明id
您可以使用URL安全ID:
entity.getKey().toUrlSafe()
所以在转换从实体到对象分配Task
元素这个ID编码在base-64 encode。从网址获取密钥的安全使用
Key.fromUrlSafe
它会保证你将永远使用全球唯一的ID。
----第三替代----
使用HATEOAS你可以指定链接accesing的Task
,所以如果该任务有一定的ID,如parentId
或userId
它基本上让他的父母节点的ID,也可能是很容易让你在HATEOAS要求,这可能因此stablish一个链接指向一个URL这样
http://base-url.com/users/ {} userId的/任务/ {}任务id
在链接中指示,表示该元素的允许的操作,所以用于查看元素使用self
,如
{
"id": "voyage-to-the-everest",
"name":"Voyage to the Everest",
"userId": "my-traveler-user-id",
"_links":{
"self":{
"href":"http://localhost:8080/users/my-traveler-user-id/tasks/voyage-to-the-everest
}
}
}
如果不是一个userId
您使用parentId
你可以做出来一个接口,所有节点指定它们是否具有父项。即使它可能是与在其中定义整个父层次一个parent
属性更加灵活:
public interface DatastoreNode{
String getParentId();
String getParentKind();
String getParentUrlTag();
DatastoreNode getParent();
}
虽然HATEOAS强烈建议你可以推断出有一个JSON结构,如
{
"id": "voyage-to-the-everest",
"name":"Voyage to the Everest",
"parent": {
parentKind: "User",
parentId: "my-traveler-user-id",
parentUrlTag: "users",
parent: {}
}
}
+1相同的URL - 这是一个完全有效的问题。谁把-1 - 关心解释? –
为什么你不使用搜索? [see] [1] [1]:http://stackoverflow.com/questions/12675664/create-a-good-looking-url-for-a-key-with-ancestors/12676004#comment17106761_12676004 –
@ Lapteuh - 你甚至看过你提到的答案吗?他们提出的查询需要完整的父键(kind + id/name),这正是OP没有的。 –