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

Support nested relationship fetching #11

Open
agarzola opened this issue Jun 16, 2018 · 3 comments
Open

Support nested relationship fetching #11

agarzola opened this issue Jun 16, 2018 · 3 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@agarzola
Copy link
Member

A Book, for example, would have a related Author, which in turn might have a related Location record for the place of birth. When fetching a book, it may be useful to have jsonmonger include not only the author, but the author’s location. The tricky part of this is that jsonmonger can’t know which type might be related to a particular property, so the model itself needs to declare this in the related config somehow.

An object might be the way to go here. Using the example above:

const Author = new Model({
  birthplace: 'relationships.location_born',
});

const Book = new Model({
  author: 'relationships.author',
}, {
  related: {
    author: {
      Author: 'birthplace',
    },
  },
});

The result should be that the include query string param would look like this:

?include=author.location_born

which the API should use to include the related author and their related birthplace in the payload.

Suggestions welcome on this interface. I think it’s a bit awkward, but can’t think of another way to accomplish this.

@agarzola agarzola added help wanted Extra attention is needed enhancement New feature or request labels Jun 16, 2018
@ghost
Copy link

ghost commented Aug 29, 2018

@agarzola Can we also add to this feature the ability to do this recursively? Let me know if you still need help on this. I saw you at Decoupled Days and learned about this project and am really wanting to use it as my management tool!

@agarzola
Copy link
Member Author

agarzola commented Aug 29, 2018

Hi, @navenedrob! 👋

So using the example above, let’s say the Location model looks like this:

const Location = new Model({
  category: 'relationships.location_type',
});

Are you wanting to declare that nested relationship in the Author model like so?

const Author = new Model({
  birthplace: 'relationship.location_born',
}, {
  related: {
    birthplace: {
      Location: 'category',
    },
  },
});

And so, when requesting a Book, the query string param would read:

?include=author.location_born.location_type

Is that what you mean?

@agarzola
Copy link
Member Author

agarzola commented Sep 2, 2018

This will also require a mechanism to avoid infinite loops. Say Location looks like this:

const Location = new Model({
  category: 'relationships.location_type',
  famous_authors: 'relationships.famous_authors',
}, {
  related: {
    famous_authors: {
      Author: 'birthplace',
    },
  },
});

Fetching a Book would result in a stack overflow as its Author requires a Location, which will require zero or more Authors, which will require Locations, which will require zero or more Authors, etc.

My current thinking on this is that once a Model has been processed as part of nested relationship fetching, subsequent uses of the same model will not include its relationships. In the example above, the Book would get its author, which would get its birthplace, which would get its famous_authors, and it stops there (Book > Author > Location > Author).

It feels a little arbitrary to stop there and not sooner (or later), but since relationships are hydrated Models, getting around it is easy. So if you needed one of those famous_authors’ books, for instance, you could easily fetch them like so:

function get_related_authors(book) {
  const related_authors = book.author.birthplace.famous_authors;
  return Promise.all( related_authors.map(author => author.fetch()) );
}

This could also be implemented as a model method or, if/when we get event hooks implemented, it can be implemented that way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

1 participant