【问题标题】:Retrieve a related item list of an item list in a firebase array检索firebase数组中项目列表的相关项目列表
【发布时间】:2016-08-24 19:34:11
【问题描述】:

我想获取 firebase 中的项目列表,但该项目的每个元素都有一个相关项目的列表。我无法获得列表,既没有使用 firebase-util 也没有使用 firebase 数组 $extend 功能。

我的 firebase 数据如下所示:

items
    item1
        name: "Item 1"
        user: user1
        images
           image1: true
           image2: true
    item2
        name: "Item 2"
        user: user1
        images:
            image3: true
            image4: true
    item3
        name: "Item 3"
        user: user2
        images:
            image5: true
            image6: true

users
    user1
        name: "User 1"
        email: "user1@email.com"
    user2
        name: "User 2"
        email: "user2@email.com"

images
    image1
        image: "data:image/jpeg;base64,/9j/..."
        thumb: "data:image/jpeg;base64,/9j/..."
    image2
        image: "data:image/jpeg;base64,/9j/..."
        thumb: "data:image/jpeg;base64,/9j/..."
    image3
        image: "data:image/jpeg;base64,/9j/..."
        thumb: "data:image/jpeg;base64,/9j/..."
    image4
        image: "data:image/jpeg;base64,/9j/..."
        thumb: "data:image/jpeg;base64,/9j/..."
    image5
        image: "data:image/jpeg;base64,/9j/..."
        thumb: "data:image/jpeg;base64,/9j/..."

我只想获取包含所有数据的项目列表。比如:

items
    item1
        name: "Item 1"
        user
            name: "User 1"
            email: "user1@email.com"
        images
            image1
                image: "data:image/jpeg;base64,/9j/..."
                thumb: "data:image/jpeg;base64,/9j/..."
            image2
                image: "data:image/jpeg;base64,/9j/..."
                thumb: "data:image/jpeg;base64,/9j/..."
    item2
        name: "Item 2"
        user
            name: "User 1"
            email: "user1@email.com"
        images
            image3
                image: "data:image/jpeg;base64,/9j/..."
                thumb: "data:image/jpeg;base64,/9j/..."
            image4
                image: "data:image/jpeg;base64,/9j/..."
                thumb: "data:image/jpeg;base64,/9j/..."
    item3
        name: "Item 3"
        user
            name: "User 2"
            email: "user2@email.com"
        images
            image5
                image: "data:image/jpeg;base64,/9j/..."
                thumb: "data:image/jpeg;base64,/9j/..."
            image6
                image: "data:image/jpeg;base64,/9j/..."
                thumb: "data:image/jpeg;base64,/9j/..."

这看起来是一个相当常见的用例,但我被困在这里。我已经尝试过this 解决方案(两种方式),但我无法让它工作。数据结构也有点不同,因为我需要关联另一个列表中的列表。

【问题讨论】:

  • 事实上,您无法根据当前结构以您要求的格式检索数据。您能否提供有关为什么要一次获取所有这些数据的信息?通常,您会得到一个用户名列表,或与第 3 项一起使用的图像列表,但通常不是一次全部。我认为您的问题可能有解决方案,理解用例会有所帮助。
  • @Jay 我想显示一个项目列表。每个项目都有一个图像列表,但我只会在列表中显示其中一个作为项目的主要图片。为什么不呢,也许在鼠标悬停时我想换一个。但至少如果我能只用一个就很好了。

标签: javascript angularjs firebase angularfire firebase-util


【解决方案1】:

目标是显示一个项目列表。

每个项目都有一个图像列表。

首先,显示项目列表和每个项目的一张图像。

建议的方法:

要填充项目列表及其初始缩略图,我们需要有一个单独的节点来从中提取初始设置。

更新的项目节点

items:
  item_id_xx: //this should be a Firebase generated node name
   name: "Item 2"
   user: "uid_for_user_1"
   images:
     image3: "data:image/jpeg;base64,/9j/..."
     image4: "data:image/jpeg;base64,/9j/..."

这是用于主列表的节点,用户可以在其中单击项目缩略图以获取更多详细信息:

item_list_for_ui
  random_node_0
    item_id: "item_id_aa"
    name: "Item 1" //if you want to display the name in the list
    initial_thumb: "data:image/jpeg;base64,/9j/..." //initial thumb
    link_to: "image1"
  random_node_1
    item_id: "item_id_xx"
    name: "Item 2"
    initial_thumb: "data:image/jpeg;base64,/9j/..."
    link_to: "image3"
  random_node_2
    item_id: "item_id_qq"
    name: "Item 3"
    initial_thumb: "data:image/jpeg;base64,/9j/..."
    link_to: "image1"

应用启动时,从 items_list_for_ui 节点填充列表。

节点很浅,包含 Firebase item_id、项目名称(如果需要)、获取初始图像缩略图的链接以及 Firebase 中主图像的 link_to。

例如:如果用户点击了Item 2的缩略图,则可以通过observeSingleEvent加载item详情,.value at

/items/item_id_xx/images/image3

您可以通过添加一个指向 item_list_for_ui 的翻转链接来解释这一点

  random_node_1
    item_id: "item_id_xx"
    name: "Item 2"
    initial_thumb: "data:image/jpeg;base64,/9j/..."
    thumb_link: "image3"
    rollover_thumb: "external link to rollover"
    rollover_link: "image4"

这种结构非常灵活,您可以通过更新相应的子节点来更改要在主列表中显示的拇指和翻转。

它也很有效,因为它避免了加载数百个项目和数百个子图像节点 - 加载所有这些节点和子节点会使 UI 过载(在某些情况下)。

使用这种结构,item_list_for_ui 是紧凑的,因此即使有数百个项目,它也只是该数据的一小部分。

您可能对自己说“自己,那是重复数据”。是的,在 Firebase 中复制数据是一个正常的过程并受到鼓励:它使结构更扁平,使查询和处理数据的速度更快。

更多阅读请看Denormalizing Data Keeps Your Breath Minty Fresh

【讨论】:

  • 感谢@Jay 的回答。但是您将如何加入数据?你会使用firebase-util 插件吗?如果是这样,怎么做?我不知道如何建立关系,因为项目 id 是动态的
  • @cor Firebase 没有连接功能,因为它不是 SQL。有多种方法可以关联数据,并且可以在 Firebase 中复制数据。我想我的回答回答了你的直接问题。您的评论/跟进是一个很好的新问题(Stackoverflow 上已经有一些答案可以解决)。查看这些答案,如果您有具体问题,请发布!
  • @cor 如果有帮助,请接受答案!然后稍微处理一下代码,并查看有关在 Firebase 中关联(加入)数据的其他一些答案。如果您遇到困难,请发布另一个问题,我们会尽力帮助您!
  • 我会支持它,但在赏金期开放时我不会接受它。它可能会出现另一个更好的答案;)
【解决方案2】:

感谢@Jay 和@Eric 的回答,他们非常有帮助,我的解决方案兼而有之。我会解释我是怎么想出来的。

首先,我更改了架构并为项目的主图片添加了一个新键。我称它为cover。但是回答原始问题,我会加载所有图像。所以这是新的items 架构:

items
    item1
        name: "Item 1"
        user: user1
        cover: image1
        images
           image1: true
           image2: true
    item2
        name: "Item 2"
        user: user1
        cover: image3
        images:
            image3: true
            image4: true
    item3
        name: "Item 3"
        user: user2
        cover: image5
        images:
            image5: true
            image6: true

然后,这就是我获得上述列表的方式(使用async 库)。这可能是实现相同目标的更好方法:

getItems: function(cb){
    var items = ref.child("items");
    items.on("value", function(snapshot){

        var item_length = snapshot.numChildren(),
            final_items = [],
            readed = 0;

        ref.child("items").on("child_added", function(item){

            var item_id = item.key(),
                itemData = item.val(),

                user = ref.child("users").child(itemData.user),
                cover = ref.child("images").child(itemData.cover),
                images = new Firebase.util.NormalizedCollection(
                       [ref.child("items").child(item_id).child("images"),'alertImages'],
                        ref.child('images')
                 ).select('images.image','images.thumb').ref();

                async.parallel([
                    function(callback){
                        user.on("value", function(user_snap){
                            callback(null, user_snap.val());
                        });
                    },
                    function(callback){
                        images.on("value", function(images_snap){
                            callback(null, images_snap.val());
                        });
                    },
                    function(callback){
                        cover.on("value", function(cover_snap){
                            callback(null, cover_snap.val());
                        });
                    }
                ], function(err, results){
                    if(!!err){
                        cb(err,null)
                    }else{
                        itemData.user = results[0];
                        itemData.images = results[1];
                        itemData.cover = results[2];

                        final_items.push(itemData);
                        readed += 1;
                        if(readed === item_length){
                            cb(null,final_items);
                        }
                    }
               });
        });
    });
}

这将输出如下内容:

item1
    name: "Item 1"
    cover:
        image: "data:image/jpeg;base64,/9j/..."
        thumb: "data:image/jpeg;base64,/9j/..."
    user
        name: "User 1"
        email: "user1@email.com"
    images
        image1
            image: "data:image/jpeg;base64,/9j/..."
            thumb: "data:image/jpeg;base64,/9j/..."
        image2
            image: "data:image/jpeg;base64,/9j/..."
            thumb: "data:image/jpeg;base64,/9j/..."
item2
    name: "Item 2"
    cover:
        image: "data:image/jpeg;base64,/9j/..."
        thumb: "data:image/jpeg;base64,/9j/..."
    user
        name: "User 1"
        email: "user1@email.com"
    images
        image3
            image: "data:image/jpeg;base64,/9j/..."
            thumb: "data:image/jpeg;base64,/9j/..."
        image4
            image: "data:image/jpeg;base64,/9j/..."
            thumb: "data:image/jpeg;base64,/9j/..."
item3
    name: "Item 3"
    cover:
        image: "data:image/jpeg;base64,/9j/..."
        thumb: "data:image/jpeg;base64,/9j/..."
    user
        name: "User 2"
        email: "user2@email.com"
    images
        image5
            image: "data:image/jpeg;base64,/9j/..."
            thumb: "data:image/jpeg;base64,/9j/..."
        image6
            image: "data:image/jpeg;base64,/9j/..."
            thumb: "data:image/jpeg;base64,/9j/..."

【讨论】:

  • 很高兴您有解决方案。密切关注其他异步调用中的那些异步调用。这可能会给您带来麻烦,因此我会经常检查您的数据 - 特别是使用 push() 并在多个设备上同时测试读取/写入数据。
  • 感谢@Jay 的建议,我在答案中寻找类似的代码,而不仅仅是代码结构。目前我还没有找到更好的东西。不过我会继续努力
【解决方案3】:

如果您拥有所有可用的数据,您可以遍历图像并将其元数据用作数据库其余部分中的键。

var itemsArr = [];
    for(var i in items) {
        var item = items[i];
        var images = [];
        for(var image in item[images]) {
            item.push(images[image]);
        }
        itemsArr.push({
            name: item.name,
            user: users[item.user],
            images: images
        });
    }

这应该产生一个如下所示的对象数组:

{
    name: "Item 1",
    user: {
        name: "User 1",
        email: "user1@email.com"
    },
    images: [{
            image: "data:image/jpeg;base64,/9j/..."
            thumb: "data:image/jpeg;base64,/9j/..."
        },{
            image: "data:image/jpeg;base64,/9j/..."
            thumb: "data:image/jpeg;base64,/9j/..."
    }]
}

【讨论】:

  • 非常感谢@Eric N,您的回答对我想要实现的目标很有帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-23
  • 2019-04-16
  • 1970-01-01
  • 1970-01-01
  • 2013-04-29
相关资源
最近更新 更多