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

feat: poc #2

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

feat: poc #2

wants to merge 3 commits into from

Conversation

jannyHou
Copy link
Owner

@jannyHou jannyHou commented Nov 29, 2018

Related to loopbackio#1952

Description see my comment below

Checklist

  • npm test passes on your machine
  • New tests added or existing tests modified to cover all changes
  • Code conforms with the style guide
  • API Documentation in code was updated
  • Documentation in /docs/site was updated
  • Affected artifact templates in packages/cli were updated
  • Affected example projects in examples/* were updated

@jannyHou jannyHou force-pushed the inclusion-spike/repository-level branch from 1b1f481 to 976334c Compare November 29, 2018 18:25
@jannyHou
Copy link
Owner Author

jannyHou commented Nov 30, 2018

This PR is a PoC of the inclusion handler proposed by @batjos in comment.

Takes findById as an example method, after adding the code that fetches the included items, TodoList.findById(1, {include: [{relation: 'todos'}]}) returns

screen shot 2018-11-29 at 11 18 04 pm

The PoC contains:

  • A InclusionHandlerFactory is created to return a handler function that fetches the included items.

  • When a relation is created, a corresponding handler will be registered in the source repository.

  • TBD: retrieve the relation metadata in InclusionHandlerFactory function:

    • return different handler functions according to the relation type
    • find the fkName in the relation definition
  • TBD(improve): Turn the factory to a class, each repository has a InclusionHandler class instance as property:

    • call this._inclusionHandler.register<TargetEntity>(targetRepositoryGetter) to register the relation handler.
    • call this._inclusionHandler.searchHandler(relationName) for each entry in the filter.include.

I also discovered a few problems worth discussion:

  • The Filter interface is not designed to describe related entities, see its definition(and Inclusion's definition).

  • I feel the inclusion handler's implementation would have overlapping code with relation repository's find method, I will investigate how to leverage those relation repositories when register the handler.

@bajtos
Copy link

bajtos commented Nov 30, 2018

@jannyHou

The Filter interface is not designed to describe related entities, see its definition(and Inclusion's definition).

Good catch, can you work with @raymondfeng to improve the type definition please?

We should eventually take a look at the JSON Schema/OpenAPI parameter schema emitted for filter too.

typeof Todo.prototype.id,
typeof TodoList.prototype.id
>(todoRepositoryGetter, 'todoListId');
this._inclusionHandler.todos = todoHandler;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block of code will be repeated a lot, I'd like to see a simpler solution, e.g. a sugar API building on top of InclusionHandlerFactory.

Ideally, the entire block should collapse to a single statement, e.g.

this._registerInclusion('todos', todoRepositoryGetter);

Under the hood, the helper should look up the definition of todos relation to learn about the target model, keyTo, and any other metadata needed. See how _createHasManyRepositoryFactoryFor is implemented.

Also based on the code in juggler, every relation needs a slightly different implementation of the inclusion handler. Please include an example/acceptance test showing how to include models via belongsTo relation to ensure requirements of other relation types were considered.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Owner Author

@jannyHou jannyHou Dec 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the belongsTo handler and it does fetch the parent instance for the child. BUT there is a problem when construct the returned data:

The Todo model only has property todoListId as the foreign key, but not todoList as its parent property. Therefore given the object

const todo = {
    id: 1,
    title: 'a todo item',
    todoListId: 1,
    todoList: {
      id: 1,
      color: red
    }
}

method toEntity(todo) won't convert property todoList and removes it in the constructed todo entity.

@bajtos
Copy link

bajtos commented Nov 30, 2018

It is important to consider the scenario where we want to fetch multiple source models and include their related models in the result, e.g. TodoList.find(1, {include: [{relation: 'todos'}]}). Under the hood, we must avoid SELECT N+1 issue. Inclusion handler must be able to fetch related models for multiple source-model ids in one query (using inq operator under the hood). The design proposed in loopbackio#1352 (comment) is already taking that into account, so does the existing implementation in juggler.

@jannyHou
Copy link
Owner Author

jannyHou commented Dec 3, 2018

Good catch, can you work with @raymondfeng to improve the type definition please?

👌 Sure, will create another PR to fix it.

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

Successfully merging this pull request may close these issues.

2 participants