adamspe / odata-resource

Node.JS+Express+REST
https://www.npmjs.com/package/odata-resource
12 stars 4 forks source link

$select in $expand #7

Open alperenboyaci opened 6 years ago

alperenboyaci commented 6 years ago

Hi $expand is working correctly without in select but I try to use $select in $expand and it doesn't work.

How can I use it ?

localhost:3000/api/campaigns/?$select=campName campCompanies&$expand=relCompany($select=comSysName), campType($select=camTypeName), campCategories($select=catName)

adamspe commented 6 years ago

As I mentioned in the previous issue $expand and $select do not currently work properly together (hence this issue).

Based on similar odata examples I would expect to implement it something like:

/book?$expand=_author&$select=title _author.name

I.e. expand the author of queried books, select the title of the found books and populate only the name of the author.

At the moment $expand will pull in the entire related document with all of its properties and you cannot, currently, select only specific properties on the expanded documents. So today you're going to get everything as opposed to a desired subset until I get a chance to implement something.

If this is a relatively isolated use case you could, as a workaround, implement it as a static relationship on your campaign resource.

E.g. (not tested, just off the top of my head)

const campaigns = new Resource({
  rel:'/api/campaigns',
  model: Campaigns
})
.staticLink('relationships_expanded',(req,res) => {
  const query = this.initQuery(this.getModel().find(),req);
  query.populate('relCompany','comSysName');
  query.populate('campType','campTypeName');
  query.populate('campCategories','catName');
  query.exec((err,objs) => {
    if(err) return Resource.sendError(res,500,'find failed',err);
    this._findListResponse(req,res,objs);
  });
});

Then you should be able to use that static relationship as if you were querying and get just the specifics for the related objects expanded. Since initQuery is used to setup the initial query the other common parameters will continue to work like $filter, $top, etc.

E.g. /api/campaigns/relationships_expanded?$select=campName&$filter=...&$top=2

adamspe commented 6 years ago

Query.exec returns a Promise so that might be cleaner than the callback (but the two would be equivalent).

I.e.

...
query.exec()
  .then(objs => this._findListResponse(req,res,objs))
  .catch(err => Resource.sendError(res,500,'find failed',err));
alperenboyaci commented 6 years ago

Hi I changed your .staticLink explanation like that and it is working just now, Thanks for your help.


var campaignsResource = new Resource({ rel: '/api/campaigns', model: campaigns, $orderby: '-createdAt', populate:({path:'relCompany campType campCategories', select:'camTypeName catName comName comSysName -_id'}), count:true })

alperenboyaci commented 6 years ago

Also can you add nested $expand on your dev plans looks like multi-level (nested) aggregate $lookup ? Thanks

adamspe commented 6 years ago

Can you please expand on your previous request? Does your thinking differ from what I had outlined earlier in this issue thread?

I.e. $expand points to the reference/s to expand and $select specifies the list of properties to include like /book?$expand=_author&$select=title _author.name

It may be a little while before I can get to working on this issue so hopefully, the workaround will do for now.