How to Publish joined Data from Array of IDs in Meteor

405 Views Asked by At

I just want to Publish the relational Data for a Publication to client, but the issue is my Relational Data field is array of ID's of a Different Collection, I tried Different Packages but all works with single Relational ID but not working with Array of relational ID's, let assume I have two Collection Companies and Meteor.users below is my Company Document Looks like

{
    _id : "dYo4tqpZms9j8aG4C"
    owner : "yjzakAgYWejmJcuHz"
    name : "Labbaik Waters"
    peoples : ["yjzakAgYWejmJcuHz", "yjzakAgYWejmJcuHz"],
    createdAt: "2019-09-18T15:33:29.952+00:00"
}

here you can see peoples field contains the user ID's as Array, so How I publish this userId's as user Documents, as for example I tried the most popular meteor package named publishComposit, when I tried Loop in Children's find, I got undefined in children i.e below

publishComposite('compoundCompanies', {
    find() {
        // Find top ten highest scoring posts
        return Companies.find({
            owner: this.userId
        }, {sort: {}});
    },
    children: [
        {
            find(company) {
                let cursors = company.peoples.forEach(peopleId => {
                    console.log(peopleId)
                    return Meteor.users.find(
                        { _id: peopleId },
                        { fields: { profile: 1 } });
                })
                //here cursor undefined
                console.log(cursors)
                return cursors

            }
        }
    ]
});

and if I implement async loop in children's find I got error like below code

publishComposite('compoundCompanies', {
    find() {
        // Find top ten highest scoring posts
        return Companies.find({
            owner: this.userId
        }, {sort: {}});
    },
    children: [
        {
            async find(company) {
                let cursors = await company.peoples.forEach(peopleId => {
                    console.log(peopleId)
                    return Meteor.users.find(
                        { _id: peopleId },
                        { fields: { profile: 1 } });
                })
                //here cursor undefined
                console.log(cursors)
                return cursors

            }
        }
    ]
});

the error occured in above code is Exception in callback of async function: TypeError: this.cursor._getCollectionName is not a function I don't know what I am exactly doing wrong here, or implementing package function not as intended any help will be greatly appropriated

EDIT: my desired result should be full user documents instead of ID no matter it mapped in same peoples array or as another fields I just want as below

{
    _id: "dYo4tqpZms9j8aG4C",
    owner: "yjzakAgYWejmJcuHz",
    name: "Labbaik Waters",
    peoples: [
        {
            profile: {firstName: "Abdul", lastName: "Hameed"},
            _id: "yjzakAgYWejmJcuHz"
        }
    ],
    createdAt: "2019-09-18T15:33:29.952+00:00"
}
1

There are 1 best solutions below

1
Harry Adel On BEST ANSWER

I ran into a similar problem couple of days ago. There are two problems with the provided code. First, using async; it's not needed and rather complicates things. Second, publishComposite relies on receiving one cursor not multiple within its children to work properly.

Below is a snippet of the code used to solve the problem I had, hopefully you can replicate it.

Meteor.publishComposite("table.conversations", function(table, ids, fields) {
  if (!this.userId) {
    return this.ready();
  }
  check(table, String);
  check(ids, Array);
  check(fields, Match.Optional(Object));

  return {
    find() {
      return Conversation.find(
        {
          _id: {
            $in: ids
          }
        },
        { fields }
      );
    },
    children: [
      {
        find(conversation) {
          // constructing one big cursor that entails all of the documents in one single go
          // as publish composite cannot work with multiple cursors at once
          return User.find(
            { _id: { $in: conversation.participants } },
            { fields: { profile: 1, roles: 1, emails: 1 } }
          );
        }
      }
    ]
  };
});