【问题标题】:DocumentID search in Firestore with a List使用列表在 Firestore 中搜索 DocumentID
【发布时间】:2021-08-18 10:35:09
【问题描述】:

我可以使用 List<String> 搜索 Firestore DocumentID 吗?

我正在尝试使用列表中的一些 documentID 选择来搜索我的收藏。该列表将由几个字符串组成。我可以使用它搜索 Firestore 集合吗?

这是列表:

 List<String> _selectedBusStop = List<String>();

这是我根据此处的列表查找 DocumentID 时使用的代码。

  Future <void> saveRoute(_selectedBusStop) async{
    Firestore.instance.collection('markers').where('BusstopName', isEqualTo: _selectedBusStop)
        .snapshots().listen((location) {
      if(location.documents.isNotEmpty){
        for (int i = 0; i < location.documents.length; i++){
          initRoute(location.documents[i].data, location.documents[i]);
        }
      }
    });
    setState(() {
    });
  }

我正在使用whereisEqualTo 还是这种方法有误?知道如何使它适用于这部分吗?提前感谢您的帮助。

更新: 这就是我的 Firestore 的样子:

List 有一些BusstopName,但不是全部。我不想只从 List 中检索 Firestore 中的所有数据。很抱歉造成这么多误会。

【问题讨论】:

  • 这段代码是否有效?如果没有,您收到的错误消息是什么?还要澄清一下,_selectedBusStop 是 documentId 还是文档中字段 BusstopName 的内容?
  • 您是否需要BusstopName(数组字段)与_selectedBusStop List 完全相同的文档,或者该数组包含来自_selectedBusStop 的任何值?
  • 如果它是一个documentId,你可以异步地向collection("markers").doc("yourDocumentId")发出请求,然后只过滤掉实际存在的documentSnacpshots。 (您可以调用 DocumentSnapshot.exists)。您需要检查 flutter firestore sdk 文档以获得正确的语法。
  • _selectedBusStop 是 DocumentID 以及文档中的数据之一。抱歉没有说清楚。 @托马斯
  • 实际上BusstopName 不是一个数组字段,它只是一个String。 DocumentID 的名称实际上与文档中的BusstopName 相同。我会更新我的问题。很抱歉造成这么多的误会。

标签: flutter google-cloud-firestore


【解决方案1】:

使用whereIn 运算符,如下所示:

   Future <void> saveRoute(_selectedBusStop) async{
    Firestore.instance.collection('markers').where('BusstopName', whereIn: _selectedBusStop)
        .snapshots().listen((location) {
      if(location.documents.isNotEmpty){
        for (int i = 0; i < location.documents.length; i++){
          initRoute(location.documents[i].data, location.documents[i]);
        }
      }
    });
    setState(() {
    });
  }

【讨论】:

  • whereIn 可能仅适用于最大长度为 10 的数组,如 described here
  • OP可以查询x的查询量,只要列表多,如果公交车站列表大于10个,比如20个,就可以查询两次,每次10个根据他们的索引。可以通过简单的方法轻松解决 list.length。这就是创建whereIn 的原因。
  • 它工作得很好,发布错误以便我们可以使用它。
  • 这是因为 Firestore 使用大小写和数字按字母顺序对它们进行排序。如果您希望它们与原始列表的顺序相同,您可以参考原始列表构建Listview,并且当您希望从 firebase 检索总线对象时,您可以告诉您的代码从检索列表,其中 object.name[来自新列表] == bustopName[来自旧列表]。
  • 使用Map 存储折线,标记的ID 为\LatLng。否则,firebase 将对它们进行二进制排序。要进行验证,请转到任何文档,并创建一个新字段,无论其名称是什么,然后添加一个名为“z”的字段。然后添加另一个名为a 的字段,它将列在其顶部。文档名称也是如此,它们按字母和数字排序。
【解决方案2】:

假设您的文档在 BusstopName 字段中存储了唯一的 ID,并且文档的实际 ID 与该字段的内容相匹配,那么您有两种可能性。

(1).where查询

  • 使用collection("markers").where("BusstopName", "=", "yourBuststopId")查询数据。
  • 这将返回一个querySnapshot Object,您可以在其上调用.size 来检查是否找到了具有该ID 的任何文档(如果您的数据库不一致,则可能超过1 个)。

(2) .doc 查询

  • collection("markers").doc("yourBuststopId")查询数据
  • 这会返回一个documentSnapshot Object,您可以在其上调用.exist 来检查文档是否真的存在。

在这两种情况下,您都需要对每个 Id 进行 1 次查询,因为 Firestore 查询仅支持相等和范围操作。看到这个similar SO question。我建议异步执行查询,否则执行时间会随着数组的大小而增加。

如果您担心成本,您只需为实际返回现有文档的结果付费。

【讨论】:

    【解决方案3】:

    你也可以试试这个:

    FirebaseFirestore.instance
      .collection('markers')
      .where('BusstopName', arrayContainsAny: ['Utar Bus Stop', 'Garden Bus Stop'])
      .get()
      .then(...);
    

    取自examples documentation

    【讨论】:

    • 这只有在BusstopName 是一个可以被搜索的数组时才有效。但我认为BusstopName 是一个String 字段。
    • 是的,BusstopNameString
    猜你喜欢
    • 1970-01-01
    • 2020-09-24
    • 2020-11-22
    • 2020-12-06
    • 1970-01-01
    • 2021-03-01
    • 2018-07-23
    • 2019-10-03
    • 1970-01-01
    相关资源
    最近更新 更多