【问题标题】:Firestore - How to update a field that contains period(.) in it's key from Android?Firestore - 如何从 Android 更新包含句点(。)的字段?
【发布时间】:2018-09-13 13:21:46
【问题描述】:

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

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

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

【问题讨论】:

  • 没有看到您的代码和对问题所在的解释,我们无能为力。
  • @DougStevenson 我添加了我的 Firestore 控制台屏幕截图。
  • @DougStevenson 当我尝试更新“com.social.game”的字段时,它创建了另一个具有嵌套字段的字段
  • 编辑您的问题以显示未按预期方式运行的代码,以及任何错误或说明。
  • @DougStevenson 我认为这是一个至少需要解决的问题。

标签: android firebase google-cloud-firestore


【解决方案1】:

你想做的都是可能的:

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

【讨论】:

  • 如果有人在 Firestore JS SDK 中搜索如何执行此操作,可以这样做(拆分路径并创建 FieldPath 实例):const fieldPath = new FieldPath('com', 'example');await docRef.update(fieldPath, FieldValue.delete());
【解决方案2】:

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

com.example.android

com_example_android

而且您可以毫无问题地更新您的资源。这可以通过在向数据库中添加数据时对密钥进行编码以非常简单的方式完成。所以请使用以下方法对密钥进行编码:

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

还有这个方法,来解码密钥:

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

编辑:

根据您的评论,如果您的密钥如下所示:

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

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

【讨论】:

  • 是的,目前我正在做同样的事情,但这不是实际的解决方案,因为密钥可能包含“_”或任何在编码时被替换的特殊字符,然后解码不会给出相同的结果。
  • 只有.(点)应该被替换。这导致了问题。对密钥进行编码的方式与对密钥进行解码的方式相同。编码前的密钥和解码后的密钥总是相同。为什么说不是呢?给我一个例子。但请记住,使用. 对您毫无帮助。
  • 假设我的密钥是“com.social.game_1”。现在编码和解码,你不会得到相同的。
  • 您是对的,但请查看我的更新答案,以解决您的问题。现在好了吗?
  • 一切都好吗?你有没有试过我上面的解决方案,它有效吗?
【解决方案3】:

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

示例:

db.collection(id).document(uid).set(new HashMap<>() {{
  put(pkg, score); 
}}, SetOptions.merge())

【讨论】:

    【解决方案4】:

    对于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)
    

    【讨论】:

      【解决方案5】:

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

      【讨论】:

      • 这不正确。只要不使用句点,就可以使用动态键。 .(点)符号用作 Cloud Firestore 文档中存在的对象之间的分隔符。任何其他符号都可以毫无问题地使用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-14
      • 2020-05-05
      • 2021-12-01
      • 2018-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多