Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Are nested services supported? #1

Open
eddyystop opened this issue Aug 3, 2017 · 7 comments
Open

Are nested services supported? #1

eddyystop opened this issue Aug 3, 2017 · 7 comments
Assignees

Comments

@eddyystop
Copy link

Interesting project.

Assume we have 2 services containing this data.

postings = [
  { _id: '100', message: 'Hello', posterId: '2000', readerIds: ['2001', '2002'] }
];
users = [
  { _id: '2000', name: 'John' },
  { _id: '2001', name: 'Marshall' },
  { _id: '2002', name: 'David' },
];

Using something like postings.get('100', { ... }), can you get back something similar to (no need to be exact) this

{ message: 'Hello', posterId: { name: 'John' }, readerIds: [ { name: 'Marshall' }, { name: 'David' }] }

Thanks.

@giapnguyen74
Copy link
Owner

I going to code a sample about nested services soon. Basically it is NextQL feature that same with how GraphQL resolve nested data. You only need define "computed" fields.

const postService = {
 fields: { _id:1, message: 1},
 computed: {
   //let compute poster from post
   poster(post){
     return db.collection('users').findOne({ posterId: post._id});
   },
   //let compute readers from post
   readers(post){
     return db.collection('posts').find({ readerIds: post._id });
   }
 }
}

const userService = {
 fields: { _id: 1, name: 1 }
 computed: {
   // let compute posts from user object
   posts(user){
    return db.collection('postings').findOne({ posterId: user._id});
   }
 }
}

Then you can query poster from user , even poster -> user -> posts

posts.get('100', {
  query: {
    message: 1,
    poster: {
      name: 1,
      posts: {
        _id: 1,
        message: 1
      }
    }
  }
}) 

@giapnguyen74
Copy link
Owner

Dear @eddyystop ,
Please check your case at Nested service sample
Run

async function test(){
    await app.service('users').create([
        { _id: '2000', name: 'John' },
        { _id: '2001', name: 'Marshall' },
        { _id: '2002', name: 'David' },
    ]).catch(() => true); //bypass if already created

    await app.service('posts').create([
        { _id: '100', message: 'Hello', posterId: '2000', readerIds: ['2001', '2002'] }
    ]).catch(() => true); //bypass if already created

    const post = await app.service('posts').get('100',{
        query: {
            _id: 1,
            message: 1,
            poster: {
                name: 1
            },
            readers: {
                name: 1
            }
        }
    });
    console.log(post);
}

test().then(() => true, console.log);

Result

node samples/posts/index.js
{ _id: '100',
  message: 'Hello',
  poster: { name: 'John' },
  readers: [ { name: 'Marshall' }, { name: 'David' } ] }

Is it ok for you?

@eddyystop
Copy link
Author

eddyystop commented Aug 4, 2017

I understand the idea. Thanks.

Feathers would tend to use app.service('posts') instead of db.collection('posts'), the computed functions need to have access to app. What do you recommend?

@giapnguyen74
Copy link
Owner

giapnguyen74 commented Aug 4, 2017

Right, I will insert app object into context next patch. Then you can access app from computed function (current, context is feathers params)

poster(post, params,{ app }) {
   return app.service('users').get(post.posterId);
}

You could check my sample - currently I use feather service directly (without app).

poster(post) {
	return Users.get(post.posterId);
},

But in my opinion, it depend on your use cases. If you use computed field replace for $populate ; it is make sense to query directly from database - it is best performance. If you want to benefit from featherjs data access layer, use service directly like my sample. Finally call app.service if you have special reason. Other case to not use app.service if you want to resolve intermediate objects, which not expose for client access. For example: you don't want allow query posts directly , so client should use users service to query their own posts.

@eddyystop
Copy link
Author

Thanks for your explaination. I'm interested in remaining database independent. So using a Model or getting app would achomplish that.

Thanks also for introducing app.

@giapnguyen74
Copy link
Owner

giapnguyen74 commented Aug 4, 2017

So use service is best for u. I extremely against use app.service. nextql-feathers is a wrapper over original feathers service. When u call app.service, it go through app -> nextql -> original service. So if use in computed, it will follow the route again without additional benefit over call original service directly. Don't forget computed fields could be n+1 issue, if your query result 10 posts; will be 10 more calls to get readers.

@eddyystop
Copy link
Author

eddyystop commented Aug 5, 2017 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants