mcadio
mcadio

Reputation: 769

How to map a deeply nested array of items from external data

I've done a mapping before, but not this deeply nested. I am trying to re-populate data from a corrupt db. I have manually reconstructed an orders array. I'm trying to look up data for each player, and then update the fields (which start out null) for each player:

Example: I start with data like this:

const orders = [
{
"paymentID": "ch_456", 
"paymentStatus": "PAID", 
"user": "[email protected]", 
"cart": {
  "username": "[email protected]", 
  "totalQty": 1, 
  "totalPrice": 80, 
  "items": [{
    "event": "Men's BB", 
    "division": "Men's", 
    "level": "BB", 
    "group": "nonpro", 
    "field": "PAL", 
    "day": "Saturday", 
    "numplayers": 2, 
    "price": 80, 
    "players": [{
      "avp_id": 1042641, 
      "first": "King", 
      "last": "Kong", 
      "waivers": [], 
      "completed": true, 
      "country": "USA", 
      "signed": false}, 
      {
      "avp_id": 1086117, 
      "first": "Jacob", 
      "last": "Ladder", 
      "waivers": [], 
      "completed": true, 
      "country": "USA", 
      "signed": false, 
      "shirt_size": "N/A"}], 
    "net": null, 
    "team": null, 
    "notes": null, 
    "paymentNote": null, 
    "waiversSent": false, 
    "active": true, 
    "paymentID": "ch_456", 
    "users": ["[email protected]"], 
    "paymentStatus": "PAID", "__v": 4}]},
"__v": 0
},{
"paymentID": "ch_123",
"paymentStatus": "PAID",
"user": "[email protected]",
"cart": {
  "username": "[email protected]", 
  "totalQty": 1,
  "totalPrice": 50,
  "items": [{
    "event": "Junior Boys 16s",
    "division": "Junior Boys",
    "level": "16s",
    "group": "nonpro",
    "field": "Main",
    "day": "Friday",
    "numplayers": 2,
    "price": 80,
    "players": [{
      "avp_id": 1022228,
      "first": "Some",
      "last": "Kid",
      "waivers": [],
      "completed": true,
      "country": "USA",
      "signed": false
      }, {
      "avp_id": 1020142,
      "first": "Justin",
      "last": "Kid",
      "waivers": [],
      "completed": true,
      "country": "USA",
      "signed": false,
      "shirt_size": "N/A"
      }
    ], 
    "net": null, 
    "team": null, 
    "notes": null, 
    "paymentNote": null, 
    "waiversSent": false, 
    "active": true, 
    "paymentID": "ch_123", 
    "users": ["[email protected]"], 
    "paymentStatus": "PAID", "__v": 4
    }
  ]
},
"__v": 0
}];

Here is my code, which I'd like to get the data from an API, and update player info to pass into a function further down:

async getLostData() {
    // get the lost orders
    console.log('start lost data import');
    // this.adminService.GetLostOrders().subscribe(orders => {
    //   console.log('load each order into system', orders);
orders.forEach(order => {
    order.cart.items.map(item => {
      const players = item.players.map(async player => {
         player = await 
           this.adminService.adminAVPReg(player.last, player.avp_id)
           .toPromise(); 
          console.log("updated player outside subscribe", player);
      });
      item.players = players;
      console.log("item", item);
    });
    // load order with updated info, create registration, and skip pmt
    // this.adminService.LoadLostOrders(order).subscribe(data => {
    //   console.log(data);
    //   console.log('finished');
    // });
  });
  console.log("orderlist", orders);
// });}

The data I'm getting logged is interesting. What comes back first from the logger is each item, followed by orderlist, and then the updated player info. Each item shows the players array listed as ZoneAwarePromise. I have no idea how to replace that with the actual data, but I can see it's not being logged in the order I expected.

How can I get the item to return with the updated data?

item logged, showing ZoneAwarePromise for player data updated info logged

Upvotes: 0

Views: 71

Answers (1)

emkay
emkay

Reputation: 807

From what I understood you are trying to do, I came up with this,

this.adminService.GetLostOrders().pipe(
  mergeMap((orders: any[]) => from(orders).pipe(
    mergeMap((order) => from(order.cart.items)),
    mergeMap((item) => of(item).pipe(
      mergeMap(_ => from(item.players)),
      mergeMap(player => this.adminService.adminAVPReg(player.last, player.avp_id).pipe(
        map(newPlayer => { player = newPlayer; return player; }))
      ),
      toArray(),
      tap(newPlayerArray => item.players = newPlayerArray)
    )),
    toArray(),
    mergeMap(_ => this.adminService.LoadLostOrders(orders))
  ))
).subscribe();

OP's Edit I implemented what you shared above, and turned it into this:

getLostData() {
    // get the lost orders
    console.log('start lost data import');
    // get manually created orders from lostdata collection
    this.adminService.GetLostOrders()
    .pipe(
      mergeMap((orders: any) => from(orders).pipe(
        mergeMap((order: any) => from(order.cart.items)),
        mergeMap((item: any) => of(item).pipe(
          mergeMap(_ => from(item.players)),
          mergeMap((player: any) => this.adminService.adminAVPReg(player.last, player.avp_id).pipe(
            map((newPlayer: any) => { 
              player.avp_id = player.avp_id;
              player.signed = player.signed;
              player.waivers = player.waivers;
              player.country = player.country;
              player.completed = true;
              player.sandbagger = false;
              player.first = newPlayer.first;
              player.last = newPlayer.last;
              player.email = newPlayer.email;
              player.address = newPlayer.address;
              player.city = newPlayer.city;
              player.state = newPlayer.state;
              player.zip = newPlayer.zip;
              player.shirt_size = newPlayer.shirt_size;
              player.ranking = newPlayer.ranking;
              player.overallRanking = newPlayer.overallRanking;
              player.notes = player.notes;
              player.phone = newPlayer.phone;
              player.adult = newPlayer.adult;
              return player; }))
          ),
          toArray(),
          tap(newPlayerArray => item.players = newPlayerArray)
        )),
        toArray(),
        tap(_ => { this.loadlostOrders(orders);
        })
      ))
    )
    .subscribe();
  }

  loadlostOrders(orders) {
    orders.forEach(order => {
      this.adminService.LoadLostOrders(order).subscribe((data) => {
            console.log("success", JSON.stringify(data));
          }, (error) => {
            console.log("error", JSON.stringify(error));
          });
    });
  }

Upvotes: 1

Related Questions