2

I have been making an API server with feathers. I have two mongoose services. Now my requirement is I want one API that has a result of both services. Let's say product-master and product are two services. The output I want is to merge both services.

To accomplish this I found one way is hook. So I tried this.

module.exports = function () {
return function (hook) {
let Product = hook.app.service('product').Model;

return new Promise(function(resolve, reject){
  Product.find({}, function(err, products) {
    var productMap = [];
    products.forEach(function(product) {
      productMap.push(products);
    });
    res.send(productMap);
    console.log(productMap);
    resolve(hook);
  });
});
};
};

Now I called the hook on before find method of product-master But I don't understand how to merge the records of product to product-master service.

And one more thing is how to create a one different API that has a merged result and custom route like http://localhost:3030/products.

Update

I found one post on stackoverflow, this might be helpful.

Rahul
  • 1,013
  • 1
  • 10
  • 24

1 Answers1

7

There are different ways for what I think you want to do. I also recommend not using the models directly but the services you want (by calling their service methods). You also want to be familiar with the API for hooks. Then you have some options:

1) Modifying the existing results

To modify the result of an existing service call, modify hook.result in an after hook:

module.exports = function () {
  return function (hook) {
    let productService = hook.app.service('product');

    return productService.find({
      paginate: false // Turn off pagination
    }).then(products => {
      hook.result.products = products;
      return hook;
    });
  };
};

Then

const myHook = require('../../hooks/myhook');

app.service('products-master').hooks({
  after: {
    get: [ myHook() ]
  }
});

This will add a products property when getting a single item from the products-master service.

2) Setting hook.result

To skip a database call you can set hook.result to what you want to return in a before hook. Keep in mind that all after hooks will still run.

3) Using a custom service

In a custom service you can do whatever you like, for example get all the things you need and put them together manually:

app.use('/all-products', {
  find() {
    return this.app.service('products-master').find(params).then(page => {
      const promises = page.data.map(masterProduct => {
        return this.app.service('products').find({
          paginate: false,
          query: {
            masterProductId: masterProduct._id
          }
        }).then(products => {
          // Add to masterProduct
          masterProduct.products = products;
        });
      });

      return Promise.all(promises).then(() => {
        // Return `page` which has the modified data
        return page;
      });
    });
  },

  setup(app) {
    this.app = app;
  }
});

In the generator a custom service can be created by choosing custom service and modifying the servicename.class.js.

4) The populate hook

Since I think you just want to populate related entities you can also have a look at the populate common hook. It can do those things automatically.

5) Using Mongoose $populate

The Mongoose Feathers adapter also supports the $populate query parameter which allows you to pull in relationships that you defined in your Mongoose model.

For more information on associations in Feathers also see this FAQ.

Daff
  • 43,734
  • 9
  • 106
  • 120