我在这里面临一个非常奇怪的决定,即在处理Firebase数据库时遇到以下情况的表现,我正在做的是生成随机customerId
以供替代使用并存储对于那个内部配置文件(我仍然使用Firebase uid
,但它仅用于"友好的数字编号"正如客户想要的那样。)
我试图做以下其中一项:
当我收到请求时:
UserVO createdUser = Json.fromJson(getRequestBodyAsJson(), UserVO.class);
CompletableFuture<String> checkCustomerIdCompletableFuture = firebaseDatabaseService.buildUniqueCustomerId();
return checkCustomerIdCompletableFuture.thenApply(customerId -> {
createdUser.setCustomerId(customerId);
return firebaseDatabaseService.addToUserProfile(createdUser.getId(), getObjectAsMapOfObjects(createdUser));
}).thenCompose(completableFuture -> CompletableFuture.completedFuture(ok(Json.toJson(createdUser))));
customerId始终在配置文件中编入索引:
"profiles":{
"$uid":{
".read":"$uid === auth.uid",
".write":"$uid === auth.uid",
},
".indexOn": ["customerId", "email"]
}
在这两种情况下,用户的个人资料应该是这样的:
"profiles" : {
"jiac4QpEfggRTuKuTfVOisRGFJn1" : {
"contactPhone" : "",
"createdAt" : 1499606268255,
"customerId" : 4998721187, // OR "A-4998721187" as string
"email" : "almothafar@example.com",
"firstName" : "Al-Mothafar",
"fullName" : "Al-Mothafar Al-Hasan",
"id" : "jiac4QpEfggRTuKuTfVOisRGFJn1",
"lastName" : "Al-Hasan2",
"updatedAt" : 1499857345960,
"verified" : false
}
}
buildUniqueCustomerId()
我有2个选项:
第一个是直接查询profiles
内customerId
,并使用queryByChild
返回唯一ID,customerId
已编入索引:
public CompletableFuture<String> buildUniqueCustomerId() {
String customerId = String.valueOf(System.currentTimeMillis()).substring(1, 9).concat(RandomStringUtils.randomNumeric(2));
CompletableFuture<String> dataSnapshotCompletableFuture = new CompletableFuture<>();
firebaseDatabaseProvider.getUserDataReference().child("/profiles").orderByChild("customerId").equalTo(customerId).limitToFirst(1)
.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot snapshot, String previousChildName) {
if (snapshot.exists()) {
buildUniqueCustomerId();
} else {
dataSnapshotCompletableFuture.complete(customerId);
}
}
@Override
public void onChildChanged(DataSnapshot snapshot, String previousChildName) {
if (snapshot.exists()) {
buildUniqueCustomerId();
} else {
dataSnapshotCompletableFuture.complete(customerId);
}
}
@Override
public void onChildRemoved(DataSnapshot snapshot) {
dataSnapshotCompletableFuture.completeExceptionally(new BusinessException("Child Remove"));
}
@Override
public void onChildMoved(DataSnapshot snapshot, String previousChildName) {
dataSnapshotCompletableFuture.completeExceptionally(new BusinessException("Child MOved"));
}
@Override
public void onCancelled(DatabaseError error) {
dataSnapshotCompletableFuture.completeExceptionally(new BusinessException(error.getMessage()));
}
});
return dataSnapshotCompletableFuture;
}
另一种方法是,创建像reservedCustomerIds
这样的新节点,检查customerId是否已经被保留,并将该id推送到该数组,以防它未被保留并返回ID以供使用,在本例中为{ {1}}是关键:
customerId
第一种方式代码需要一些清理,但它只是快速启动,但你可以看到代码中的第二种方式更短但是存储该ID的又一步,它还有额外的存储空间public CompletableFuture<String> buildUniqueCustomerId() {
String customerId = "A-".concat(String.valueOf(System.currentTimeMillis()).substring(1, 9).concat(RandomStringUtils.randomNumeric(2)));
String customerRef = String.format("/reservedCustomerIds/%s", customerId);
return firebaseDatabaseProvider.fetchObjectAtRef("/usersData".concat(customerRef))
.thenCompose(dataSnapshot -> {
if (dataSnapshot.getValue() != null) {
return buildUniqueCustomerId();
} else {
return CompletableFuture.completedFuture(customerId);
}
})
.thenCompose((newCustomerId) -> this.updateObjectData(true, customerRef).thenApply(aVoid -> newCustomerId))
.exceptionally(throwable -> {
Logger.error(throwable.getMessage());
return null;
});
}
仅用于支票ID:
reservedCustomerIds
哪一项性能最佳,更快检查customerId的唯一性?使用customerId作为额外存储的关键,或在"reservedCustomerIds" : {
"A-4998721187" : true,
"A-4998722342" : true,
"A-4998722222" : true,
"A-4998724444" : true,
"A-4998725555" : true,
}
的配置文件中使用customerId本身?
P.S:在评论或完整答案中,如果你能给我一个关于firebase索引或查询的链接,我会非常感激。
答案 0 :(得分:2)
第二种方法称为fanning out and is covered in the Firebase documentation。它的优点是您可以在不需要查询的情况下读取ID,这意味着其规模没有实际限制。
但是你需要为每个客户做额外的阅读。虽然这些并不像大多数开发人员所期望的那么慢(参见Speed up fetching posts for my social network app by using query instead of observing a single event repeatedly),但总有一个可用性限制。
很难说&#34;这比那更好&#34;。如果有,Firebase实时数据库文档将明确(并且响亮)。但更平坦的结构,散布数据,而不是查询数百万个节点以找到1都有助于拥有一个可以平滑扩展的应用程序。另请参阅Are Firebase queries scalable,Firebase Performance: How many children per node?。