Android Firestore-如何更新其中包含句点(.)的字段';安卓的钥匙是什么?

Android Firestore-如何更新其中包含句点(.)的字段';安卓的钥匙是什么?,android,firebase,google-cloud-firestore,Android,Firebase,Google Cloud Firestore,更新包含句点(.)的字段未按预期工作。 在文档中,可以通过提供点分隔的字段路径字符串或提供FieldPath对象来更新嵌套字段。 所以,如果我有一个字段,它的键是“com.example.android”我如何更新这个字段(从android) 在我的场景中,如果文档不存在,我必须设置文档,否则更新文档。所以,第一个集合是创建包含如上所述句点的字段,然后尝试更新它正在创建具有嵌套字段的相同字段,因为它包含句点 db.collection(id).document(uid).update(pkg,

更新包含句点(.)的字段未按预期工作。 在文档中,可以通过提供点分隔的字段路径字符串或提供FieldPath对象来更新嵌套字段。 所以,如果我有一个字段,它的键是
“com.example.android”
我如何更新这个字段(从android)

在我的场景中,如果文档不存在,我必须设置文档,否则更新文档。所以,第一个集合是创建包含如上所述句点的字段,然后尝试更新它正在创建具有嵌套字段的相同字段,因为它包含句点

db.collection(id).document(uid).update(pkg, score)

之所以发生这种情况,是因为
(点)符号被用作云Firestore文档中存在的对象之间的分隔符。这就是你有这种行为的原因。要解决此问题,请避免在对象的键内使用
符号。因此,为了解决这个问题,您需要更改设置该键的方式。因此,请更改以下密钥:

com.example.android

你可以毫无问题地更新你的财产。这可以通过一种非常简单的方式完成,即在向数据库添加数据时对密钥进行编码。因此,请使用以下方法对密钥进行编码:

private String encodeKey(String key) {
    return key.replace(".", "_");
}
private String decodeKey(String key) {
    return key.replace("_", ".");
}
此方法用于解码密钥:

private String encodeKey(String key) {
    return key.replace(".", "_");
}
private String decodeKey(String key) {
    return key.replace("_", ".");
}
编辑:

db.collection(id).document(uid).set(new HashMap<>() {{
  put(pkg, score); 
}}, SetOptions.merge())
根据您的评论,如果您有一个如下所示的密钥:

com.social.game_1
这种情况可以用一种非常简单的方法解决,即对密钥进行两次编码/解码。首先将
编码为
@
,然后将
编码为
。解码时,首先将
解码为
,然后将
@
解码为
。让我们举一个非常简单的例子:

String s = "com.social.game_1";
String s1 = encodeKeyOne(s);
String s2 = encodeKeyTwo(s1);
System.out.println(s2);
String s3 = decodeKeyOne(s2);
String s4 = decodeKeyTwo(s3);
System.out.println(s4);
以下是相应的方法:

private static String encodeKeyOne(String key) {
    return key.replace("_", "@");
}

private static String encodeKeyTwo(String key) {
    return key.replace(".", "_");
}

private static String decodeKeyOne(String key) {
    return key.replace("_", ".");
}

private static String decodeKeyTwo(String key) {
    return key.replace("@", "_");
}
输出将是:

com_social_game@1
com.social.game_1 //The exact same String as the initial one

但请注意,这只是一个示例,您可以根据应用程序的用例对该密钥进行编码/解码。在编码/解码字符串时,这是一种非常常见的做法。

键不应包含句点(
),因为它与嵌套字段冲突。一个理想的解决方案是不要使关键点是动态的,那些是无法确定的。然后,您可以完全控制按键的设置方式。

您可以执行以下操作:

FieldPath field = FieldPath.of("com.example.android");
db.collection(collection).document(id).update(field, value);

现在修好了。它不是那样发生的。

克服这种行为的最佳方法是使用带有
merge:true
参数的
set
方法

示例:

db.collection(id).document(uid).set(new HashMap<>() {{
  put(pkg, score); 
}}, SetOptions.merge())
db.collection(id).document(uid).set(新的HashMap(){{
put(包装、评分);
}},SetOptions.merge())
用于js版本

firestore架构:

 cars: {
   toyota.rav4: $25k
 }
js代码

  const price = '$25k'
  const model = 'toyota.rav4'
  const field = new firebase.firestore.FieldPath('cars', model)
  return await firebase
    .firestore()
    .collection('teams')
    .doc(teamId)
    .update(field, price)

如果看不到您的代码和错误的解释,我们将无能为力。@DougStevenson我添加了我的firestore控制台屏幕截图。@DougStevenson当我试图更新“com.social.game”的字段时,它创建了另一个字段,该字段具有嵌套字段。请编辑您的问题,以显示未按预期方式运行的代码,以及任何错误或描述。@DougStevenson我认为这至少是一个需要解决的问题。是的,目前我也在这样做,但这不是实际的解决方案,因为密钥可能包含“\uu”或任何在编码时被替换的特殊字符,然后解码将不会给出相同的结果。只应替换
(点)。这造成了问题。你对密钥进行编码的方式和解码密钥的方式是一样的。编码前的密钥和解码后的密钥始终相同。你为什么说那不是?给我举个例子。但是请记住,使用
对您毫无帮助。假设我的密钥是“com.social.game_1”。现在编码和解码,你不会得到相同的。你是对的,但请看我的更新答案,解决你的情况。现在没事了?一切都好吗?你试过我上面的解决方案了吗?不正确。只要不使用句点,就可以使用动态关键点。
(点)符号用作Cloud Firestore文档中存在的对象之间的分隔符。可以毫无问题地使用任何其他符号。如果有人在Firestore JS SDK中搜索如何执行此操作,这就是可能的方式(拆分路径并创建FieldPath实例):
const FieldPath=new FieldPath('com','example')
等待docRef.update(fieldPath,FieldValue.delete())不想解释为什么?