使用angular保存firebase中的结构化数据

时间:2016-03-12 23:30:54

标签: javascript angularjs firebase firebase-realtime-database angularfire

我理解在firebase中保存structured data的概念和最佳做法,但我不清楚如何将数据实际保存到多个位置并提供所需的交叉引用。

{
  articles: {
    -KBX5TurV9uJTeiR26-N: {
       title: 'post title 1',
       body: 'post body goes here',
       imagesRef: {
          -KBX5XOYASP7h2ZPOKmg: true
       }
    },
    -KCe7cy6QC29WRYap0D1: {
       title: 'post title 2',
       body: 'post body goes here',
       imagesRef: {
          -KBX5XOYASP7h2ZPOKmg: true
       }
    }
  }
  images: {
    -KBX5XOYASP7h2ZPOKmg: {
       image: 'data:image/gif;base64,R0lGODlhZABkAOYAAPj4...',
       articlesRef: {
          -KBX5TurV9uJTeiR26-N: true,
          -KCe7cy6QC29WRYap0D1: true
       }
    }
  }
}

以上架构是我想要的一个例子。在提交由标题,正文和图像字段组成的表单时,我需要将标题和正文发布到文章对象,然后将图像发布到图像对象,然后使用交叉引用更新imagesRef和articlesRef对象。在Angular中,最好的方法是什么?我也将angularfire作为项目的一部分。

我是角度和火力新手的新手,但我想我需要做两篇文章一篇文章和一篇图片来保存它们并生成独特的ID。然后我需要一些如何等待两者成功,获取唯一ID并对两个对象进行更新以保存交叉引用。这是我到目前为止所做的,但不知道如何进一步采取行动......

     $scope.AddPost = function(){

        var ref = new Firebase(FIREBASE_URI);
        var newArticleRef = ref.child('articles').push();
        var newArticleKey = newArticleRef.key();

        // Create the data we want to update
        var addNewPost = {};
        addNewPost["articles/" + newArticleKey] = {
            title:   $scope.article.title,
            post:    $scope.article.post
        };

        if ($scope.image) {

            var newImageRef = ref.child('images').push();
            var newImageKey = newImageRef.key();

            // Add image...
            addNewPost['images/' + newImageKey] = {
                image: $scope.image
            };

            //Add article ref...
            addNewPost['images/' + newImageKey + '/articles/' + newArticleKey] = true;

            //Add cross ref to article...
            addNewPost['articles/' + newArticleKey + '/image/' + newImageKey] = true;

        }


        // Do a deep-path update
        ref.update(addNewPost, function(error) {
                if (error) {
                    console.log("Error:", error);
                }
        });

    });

更新:我更新了代码示例以使用multi-location updatesfan-out approach,但我在保存时遇到错误...

Error: Firebase.update failed: First argument contains a path /images/-KCpx-Pj9oMM-EWN9irS that is ancestor of another path /images/-KCpx-Pj9oMM-EWN9irS/articles/-KCpx-Pj9oMM-EWN9irR
at Error (native)
at ig (http://localhost:8000/app/assets/js/plugins.js:430:390)
at jg (http://localhost:8000/app/assets/js/plugins.js:431:383)
at X.update (http://localhost:8000/app/assets/js/plugins.js:564:369)
at r.$scope.AddPost (http://localhost:8000/app/assets/js/app.js:171:17)
at fn (eval at <anonymous> (http://localhost:8000/app/assets/js/plugins.js:216:110), <anonymous>:4:212)
at e (http://localhost:8000/app/assets/js/plugins.js:257:177)
at r.$eval (http://localhost:8000/app/assets/js/plugins.js:133:446)
at r.$apply (http://localhost:8000/app/assets/js/plugins.js:134:175)
at r.scopePrototype.$apply (chrome-extension://ighdmehidhipcmcojjgiloacoafjmpfk/dist/hint.js:1427:22)

警告:我尝试了以下操作。它创建了一个单独的对象,并没有触发JS错误,但它消灭了我的数据库,只留下了新创建的对象。没有损失太多,因为我现在正在进行一些测试,但我认为我应该警告别人。不要这样做......

        addNewPost.Articles = {};
        addNewPost.Articles[newArticleKey] = {};
        addNewPost.Articles[newArticleKey].title = $scope.article.title;
        addNewPost.Articles[newArticleKey].post = $scope.article.post;

        var newImageRef = ref.child('images').push();
        var newImageKey = newImageRef.key();

        addNewPost.images = {};
        addNewPost.images[newImageKey] = {};
        addNewPost.images[newImageKey].image = $scope.image;
        addNewPost.images[newImageKey].articles = {};
        addNewPost.images[newImageKey].articles[newArticleKey] = true;

        addNewPost.Articles[newArticleKey].image = {};
        addNewPost.Articles[newArticleKey].image[newImageKey] = true;

1 个答案:

答案 0 :(得分:1)

不确定是最好的答案,但我发现以下内容对我有用。它利用Frank van Puffelen的建议来使用多位置更新。设置以下代码以支持使用现有图像添加新图像或根本不使用图像。我认为同样适用于类别,标签或用户中的任何元数据。

    .controller('AddPostController', ['$scope','$firebaseArray','FIREBASE_URI',
    function($scope,$firebaseArray,FIREBASE_URI) {

        var ref = new Firebase(FIREBASE_URI);

        $scope.AddPost = function(){

            var newArticleRef = ref.child('articles').push();
            var newArticleKey = newArticleRef.key();

            var newImageRef = ref.child('images').push();
            var newImageKey = newImageRef.key();

            // Create the data we want to update
            var addNewPost = {};

            // Add new article...
            addNewPost["articles/" + newArticleKey] = {
                title:   $scope.article.title,
                post:    $scope.article.post,
                emailId: user,
                '.priority': user
            };

            if ($scope.image) {

                // Add new image reference to new article...
                addNewPost["articles/" + newArticleKey].image = {};
                addNewPost["articles/" + newArticleKey].image[newImageKey] = true;

                // Add new image...
                addNewPost['images/' + newImageKey] = {
                    image: $scope.image,
                    emailId: user,
                    '.priority': user
                };

                // Add article reference to new image...
                addNewPost['images/' + newImageKey].articles = {};
                addNewPost['images/' + newImageKey].articles[newArticleKey] = true;

            } else if ($scope.article.image) {

                // Add existing image reference to article...
                addNewPost["articles/" + newArticleKey].image = {};
                addNewPost["articles/" + newArticleKey].image[$scope.article.image] = true;

                // Add new article reference to existing image...
                addNewPost['images/' + $scope.article.image + '/articles/' + newArticleKey] = true;

            }

            // Do a deep-path update
            ref.update(addNewPost, function(error) {
                if (error) {
                    console.log("Error:", error);
                }
            });

        };

    }]);