Фильтр запросов базы данных AngularJS Firebase на основе другой базы данных

#angularjs #firebase #angularjs-ng-repeat #firebase-realtime-database

#angularjs #firebase #angularjs-ng-repeat #firebase-база данных в реальном времени

Вопрос:

Я получаю значения, сохраненные в поле «проекты» под данными текущего пользователя в базе данных Firebase под названием users:

первый метод:

 var promise = MyUser.user();
promise.then( function onSuccess(user) {
    $scope.userprojectskeys  = user.projects;
});
  

второй способ:

 var keyquery = DatabaseRef.ref('/users/'   userId).orderByKey().once("value")
    .then(function onSuccess(snapshot) {
        snapshot.child("savedprojects").forEach(function(childSnapshot) {
            var userprojects = childSnapshot.val();
            console.log("my list is :", userprojects );
        });
    });
  

$scope.userprojectskeys первого метода и userprojects второго метода оба возвращают необходимые данные:

вывод первого метода:

введите описание изображения здесь

вывод второго метода:

 my list is : -KUTLAZENGlxtzCtEfaZ
my list is : -KUTLM8r_kmVSTaxzLW5
my list is : -KUTPrs6ARZXjbjtNr7O
  

С другой стороны, у меня есть другая функция, которая получает список дочерних элементов в другой базе данных, называемой projects, например, следующим образом:

 var projectquery = DatabaseRef.ref("projects").orderByKey().equalTo("-KUTPrs6ARZXjbjtNr7O");
$scope.projectslist = $firebaseArray(projectquery);
  

то, что я делаю сейчас, — это повторение полей объекта в $scope.projectslist , отображение полей для каждого проекта.

 <tr ng-repeat="obj in projectslist">
    <td>{{ obj.field1}}</td>
    <td>{{ obj.field2 }}</td>
    <td>{{ obj.field3 }}</td>
    <td>{{ obj.field4 }}</td>
</tr>
  

Вопрос :

как можно передать приведенный выше список ключей проекта, полученных ранее из данных текущего пользователя (либо с использованием первого, либо второго метода), в последнюю функцию, которая показывает проекты и фильтрует их по ключу в equalTo() ?

но, как вы можете видеть, я передаю один идентификатор проекта вручную в свой фильтр equalTo , и он работает. Но мне нужно передать все ключи в equalTo.

одним из предлагаемых методов является:

один из предлагаемых методов заключается в объединении этих двух функций следующим образом:

 $scope.projectslist = [];
DatabaseRef.ref('/users/'   userId).orderByKey().once("value")
    .then(function onSuccess(snapshot) {
        snapshot.child("projects").forEach(function (childSnapshot) {
            var userprojects = childSnapshot.val();
            var projectquery = DatabaseRef.ref("projects").orderByKey().equalTo(userprojects);
            $scope.projectslist.push($firebaseArray(projectquery));
        });
    });
  

но это безуспешно! в таблице отображаются строки, но внутри нет значения:http://imgur.com/uByHT3c
вот скриншот отладчика:http://i.imgur.com/TaDZLlk.png

Обновить:

вот структура моего users дочернего элемента в mydatabase в firebase:
введите описание изображения здесь

В котором вы можете видеть пять пользователей, и для каждого пользователя есть несколько полей, одно из которых является полем, в котором хранятся ключи пользовательских проектов, и в этом примере у пользователя есть четыре ключа проекта.

и вот дочерние проекты в firebase mydatabase:
введите описание изображения здесь

здесь мы видим глобальное представление моей базы данных firebase. Итак, цель состоит в том, чтобы искать ключи проектов у пользователей, а затем показывать соответствующие проекты из базы данных проектов, то есть повторно повторять поля этих проектов.

Обновить:

вот журнал консоли после предложения Zura:

 $scope.projectslist = [];
DatabaseRef.ref('/users/'   userId).orderByKey().once("value")
    .then(function onSuccess(snapshot) {
        snapshot.child("projects").forEach(function (childSnapshot) {
            var userprojects = childSnapshot.val();
            //console.log("loaded. Data: ", userprojects);
            var projectquery = DatabaseRef.ref("projects").orderByKey().equalTo(userprojects);

            var list = ($firebaseArray(projectquery));
            console.log("list: ", list);

        });
    });
  

каждый список содержит информацию, которая мне нужна для каждого проекта текущего пользователя. Идеально!
Но как получить к ним доступ и сохранить их в $scope , чтобы иметь возможность вызывать это в моем html?

введите описание изображения здесь

Обновить:

Я могу показать только последний проект, передав список в $scope:
показанный проект является последним в каждой итерации. Вопрос в том, как я могу показать все итерации forEach и передать его в массив?

обновление 25.10.2016:

вот обновленная версия кода, который объединяет объекты: сначала один, затем первые два вместе, первые три и, наконец, все объекты, объединенные в один большой массив, смотрите Журнал консоли ниже:

  $scope.projectslist = [];

DatabaseRef.ref('/users/'   userId).orderByKey().once("value")
    .then(function onSuccess(snapshot) {
        snapshot.child("projects").forEach(function (childSnapshot) {
            var userprojects = childSnapshot.val();
            var projectquery = DatabaseRef.ref("projects").orderByKey().equalTo(userprojects);

            var list = $firebaseArray(projectquery);

            $scope.list = $firebaseArray(projectquery);
            console.log("list: ", $scope.list);
            list.$loaded(function(){
                 $scope.projectslist = $scope.projectslist.concat(list);
                 console.log("loaded: ", $scope.projectslist);
            });

        });
    });
  

введите описание изображения здесь

и каждый объект напрямую содержит нужную мне информацию, как показано на предыдущем снимке экрана объекта.

Ответ №1:

Рекомендации

  • Когда это возможно, всегда используйте angularfire вместо оригинальных обещаний firebase. AngularFire автоматически выполняет 3-стороннюю привязку $scope.$apply . Так что вам не нужно думать об этом.

  • Используйте $firebaseObject вместо $firebaseArray , если вы извлекаете только один объект.

————————————————————————————————————————————

Ваша проблема в следующем коде.

 $scope.projectslist.push($firebaseArray(projectquery));
  

firebaseArray() возвращает массив, и что push делает метод, так это то, что он помещает данный параметр в конец массива. Итак, здесь у вас будет массив, который также содержит массивы.
Вместо этого вы хотите объединить существующий массив с $firebaseArray(projectquery) .

Я предлагаю попробовать следующий код.

 var projectquery = DatabaseRef.ref("projects").orderByKey().equalTo(userprojects);
var list = $firebaseArray(projectquery);
list.$loaded(function(){
    $scope.projectslist.contact(list);
});
  

И если вы используете angularfire, я думаю, вам следует изменить выборку пользовательских проектов, также используя $firebaseObject . И вам не нужно использовать orderByKey , потому что вы извлекаете только один объект.

 var user = $firebaseObject(DatabaseRef.ref('/users/'   userId));
user.$loaded(function(){
    console.log("User loaded. Data: ", user);
    angular.forEach(user.projects, function(value, key){
        var projectquery = DatabaseRef.ref("projects").orderByKey().equalTo(key);
        // var list = $firebaseArray(projectquery);
        // list.$loaded(function(){
        //    $scope.projectslist = $scope.projectslist.concat(list);
        // });
        // or shortly. Replace 4 lines above with this line.
        $scope.projectslist.push($firebaseObject(projectquery));
    });
});
  

Обновить

Поскольку вы получаете только один список, было бы лучше попробовать $firebaseObject получить объект и поместить его в массив.

ОБНОВЛЕНИЕ 25.10.2016:

Теперь ваша проблема здесь.

 DatabaseRef.ref('/users/'   userId).orderByKey().once("value")
    .then(function onSuccess(snapshot) {
        snapshot.child("projects").forEach(function (childSnapshot) {
  

Это сделано не в соответствии с моим предложением. Вы не используете angularfire, и html НЕ перекомпилируется автоматически. Вы должны вызывать $scope.$apply в конце onSuccess promise или лучше… Вы должны использовать подход angularfire, $firebaseObject который автоматически вызывает $scope.$apply .

 var user = $firebaseObject(DatabaseRef.ref('/users/'   userId));
user.$loaded(function(){
    console.log("User loaded. Data: ", user);
    angular.forEach(user.projects, function(value, key){
  

Комментарии:

1. Мой первый вопрос: Что такое контакт в вашей последней строке добавляется в список? откуда он взялся? что он делает? У меня его нет в исходном коде в вопросе. Во-вторых, я пытался реализовать ваш ответ, но безуспешно. И когда я реализую ваш второй код, я получаю предупреждение о дублирующемся объявлении для пользователя . Не могли бы вы, пожалуйста, пересмотреть свой ответ и дать мне знать, если у вас есть какие-либо предложения?

2. Я добавил запрошенные скриншоты структуры моей базы данных.

3. вы имеете в виду объединение с помощью контакта для объединения? в любом случае, я тоже пробовал это, но безуспешно.

4. Я заменил $scope.projectslist.push($firebaseArray(projectquery)); вашим предложением: var list = $firebaseArray(projectquery); в списке есть то, что мне нужно! но они хранятся в [0] каждого массива. Как их объединить? вот мой консольный журнал для списка , добавленного к вопросу..

5. Да, это должно быть concat вместо contact. Извините за эту ошибку с опечаткой. И после конкатенации он возвращает новый массив вместо изменения существующего. Проверьте мой обновленный ответ.