gpt4 book ai didi

java - firebase查询性能orderByChild + .indexOn VS orderByKey

转载 作者:行者123 更新时间:2023-12-02 02:43:14 25 4
gpt4 key购买 nike

我在这里面临一个非常奇怪的决定,涉及处理 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() :

第一个是直接在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,在本例中为 customerId是一个关键:

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仅用于检查 ID:

"reservedCustomerIds" : {
"A-4998721187" : true,
"A-4998722342" : true,
"A-4998722222" : true,
"A-4998724444" : true,
"A-4998725555" : true,
}

哪一个性能最好,可以更快地检查 customerId 唯一性?使用 customerId 作为额外存储的 key ,或在配置文件中使用 customerId 本身 .indexOn

P.S:在评论或完整答案中,如果您能给我一个有关如何建立 Firebase 索引或查询的链接,我将非常感激。

最佳答案

第二种方法称为 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 ),但始终存在可用性限制。

很难说“这个比那个更好”。如果有的话,Firebase 实时数据库文档将对此进行明确(且响亮)的说明。但更扁平的结构、扇形数据以及无需查询数百万个节点来查找 1 都有助于拥有可平滑扩展的应用程序。另请参阅Are Firebase queries scalable , Firebase Performance: How many children per node? .

关于java - firebase查询性能orderByChild + .indexOn VS orderByKey,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45076993/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com