加入扁平化数据

时间:2017-02-19 20:30:08

标签: angular typescript firebase firebase-realtime-database angularfire2

我想将trainings-table的数据加入我的users-table

它的数据结构如下:

 - users
  - key1
     - name
     - trainingIds
         - t_key1
         - t_key3
 - trainings
  - t_key1
     - name
     - description
  - t_key2
     - name
     - description
  - t_key3
     - name
     - description

我已经搜索过Stackoverflow并找到了一个不错的solution。不幸的是,我无法解决Romain Bruckert提到的问题。

这是我的代码:

this.visibleUser$ = af.database.list(`${this.path}`)
        .map( users => {
          console.log( users );
          return users.map( user => {
            console.log( user );
            console.log( user.trainingIds );
            user.trainingIds.map( trainingIdsMap => {
              af.database.list(`dev/trainings/${trainingIdsMap.$key}`)
              .map( tr => {
                trainingIdsMap = tr;
              });
            });
            return user
          });
        }) as FirebaseListObservable<any>;

这是Firebase数据结构:

{
  "trainings" : {
    "-KdGENe4XiCyEowgYGbu" : {
      "description" : "lala beschreibung",
      "name" : "Bring Sally Up Challenge"
    },
    "-KdGGjQtvdLPWZOSHjKP" : {
      "description" : "Beschreibung für liegestütz",
      "name" : "Ligestütze"
    },
    "-KdGH3qNKCWGnW1kebMj" : {
      "active" : false,
      "description" : "Des funktioniert ja wirklich",
      "name" : "Wahnsinn"
    },
    "-KdHSzTb63L9_6qw461X" : {
      "description" : "klettern klettern klettern",
      "name" : "8a Training"
    },
    "-KdI2OXgEO0GnIqDXaDT" : {
      "description" : "Bes",
      "name" : "Test"
    }
  },
  "users" : {
    "8faYwT4xp4SoXzU3HPnc2rIsqyp1" : {
      "email" : "email@web.de",
      "trainingIds" : {
        "-KdGH3qNKCWGnW1kebMj" : false,
        "-KdHSzTb63L9_6qw461X" : true
      },
      "username" : "didi"
    },
    "EWt2O16J9MasAwuoi92PQ3h66Bw2" : {
      "email" : "email@yahoo.de",
      "username" : "ChrisB"
    }
  }
}

正如Clark所建议的,我已经导入了rxjs map运算符,但这并没有解决问题。问题似乎是trainingIds列表。它们不像预期的那样作为数组返回,而是作为对象返回。这可以在控制台日志中看到。

Consolelog:

任何想法如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

这是一个有效的解决方案。

查看此代码的live Plunker。您将看到控制台记录用户及其已解决的培训。

const visibleUser$ = user$
  // Flatten the array of users to emit users individually.
  .mergeMap(val => val)
  // Project each user to an observable to get its trainings.
  .mergeMap(user => {
    // Array of observables fetching the trainings for the current user.
    const trainingsArr = user.trainingIds.map(trainingId => getTraining(trainingId));
    // Unwrap the trainings and merge them with the current user.
    return Rx.Observable.from(trainingsArr)
      .mergeAll()
      .toArray()
      .map(userTrainings => Object.assign(user, {trainings: userTrainings}));
  })
  .toArray()

visibleUser$.subscribe(val => console.log(val));

控制台将记录:

[{
  key: "key1",
  name: "user1",
  trainingIds: ["t_key1", "t_key3"],
  trainings: [  // Array of unwrapped trainings for this user
    {
      desc: "Desc 1",
      key: "t_key1",
      name: "Training 1"
    },
    {
      desc: "Desc 3",
      key: "t_key3",
      name: "Training 3"
    }
  ]
},
{
  key: "key2",
  name: "user2",
  // ...
}]

在Plunkr中,我已经用包含假数据的observable替换了实时Firebase调用。更具体地说,在我的示例中,您需要替换:

  • user$af.database.list(this.path)
  • getTraining(trainingId)af.database.list(dev/trainings/${trainingIdsMap.$key})

如果您对代码有疑问,请与我们联系。

次要注意:在您的代码中“af.database.list(${this.path})”可以替换为af.database.list(this.path)。如果所有字符串包含的都是变量,则无需插值。 :)