恶魔难题!使用 .where() 作为数组和字符串



我正在尝试使用firestore的.where((功能来检测某个字符串是否在数据库中的数组中。我尝试通过添加括号和其他东西来表示数组的各个部分来操作函数的第一个参数,但无济于事。

//in this section I am getting the "yourLikes" integer (unrelated to the problem)
var liks = [];
var tempLiks = []
db.collection("users").where("uid", "==", uid)
.get()
.then(function(querySnapshot) {
    querySnapshot.forEach(function(doc) {
      tempLiks = doc.data().yourLikes;
      // I am using a setTimeout() function to allow firebase to 
      // process the previous query and give me the doc.data().yourLikes for tempLiks
      setTimeout(function(){
      //Right here, the "usersLiked" data is an array, with a bunch of different values. 
      // I am trying to see if one of those values is doc.data().uid from my previous query. (I think) this is the problem.
       db.collection("memeInfo").where("usersLiked", "==", doc.data().uid)
        .get()
        .then(function(querySnapshot) {
            querySnapshot.forEach(function(doc) {
              for (var i = 0; i < tempLiks.length; i++) {
                liks.push([tempLiks[i],doc.data().likes])
                console.log(liks)
              }
            })
          })
      },500)

如果有人有一个解决方案来查询单个值是否在数组中而不永远使用 for 循环(我在 usersLike 数组中可能有数千个值(,那将不胜感激。

应使用 array_contains 运算符根据数组值进行筛选,请参阅 https://firebase.google.com/docs/firestore/query-data/queries#array_membership。

因此,您必须按如下方式调整代码:

//....
db.collection("memeInfo").where("usersLiked", "array-contains", doc.data().uid)
        .get()
        .then(function(querySnapshot) {...})

额外备注:使用 setTimeout() 来管理对 Firestore 的查询的异步方面不是一种正确的方法(不能保证查询将在 500 毫秒内完成(。您应该通过 get() 方法返回的承诺来管理异步性。特别是,由于您要并行触发多个查询(通过循环(,因此需要使用Promise.all() .


根据您的评论进行更新。您可以按如下方式使用Promise.all()

var liks = [];
var tempLiks = [];
db.collection('users')
  .where('uid', '==', uid)
  .get()
  .then(function(querySnapshot) {
    // Here the Promise returned by the get() method is fulfilled, so you do have the results of the query and you do'nt need to use setTimeout
    var queries = [];
    querySnapshot.forEach(function(doc) {
      tempLiks = doc.data().yourLikes;
      //We push each query to the queries array
      queries.push(
        db
          .collection('memeInfo')
          .where('usersLiked', '==', doc.data().uid)
          .get()
      );
    });
    //Then we call Promise.all()
    return Promise.all(queries);
  })
  .then(function(results) {
    //As explained in the doc "The returned promise is fulfilled with an array containing all the values of the iterable passed as argument (the queries array)."
    //So result is an array of QuerySnapshots, since the get() method returns a QuerySnapshot
    //Do whatever you want with the array
    console.log(results);
    results.forEach(function (querySnapshot) {
        querySnapshot.forEach(function (doc) {
            //.....
        });
    });
  });

最新更新