Огненная загадка!Использование .where () для массивов и строк - PullRequest
1 голос
/ 03 июня 2019

Я пытаюсь использовать функцию .where () в firestore, чтобы определить, находится ли определенная строка в массиве в базе данных.Я попытался манипулировать первым параметром функции, добавив скобки и другие элементы для обозначения частей массива, но безрезультатно.

//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 навсегда (возможно, у меня будут тысячи значений в массиве usersLiked), это было бы очень полезно.

1 Ответ

2 голосов
/ 03 июня 2019

Вы должны использовать оператор 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) {
            //.....
        });
    });
  });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...