Thursday, August 17, 2017

Why is this nested relation in LoopBack returning duplicate results?

Leave a Comment

When I query to include a nested model – e.g. GET /api/Widgets/1?filter={include: {"foos": "bars"}} – I get duplicate foos in my results. I thought this was due to a LEFT JOIN or something like that, as I'm using MySQL, but when I run LoopBack in the loopback:connector:mysql debug mode, I can see that the query for the initial widget runs once, but that the query for foo runs twice, and the query for bar runs twice. Why is this behavior occurring, and what can I alter (my models, my code or my expectations)?

Models:

{   "name": "Widget",   ...   "relations": {     "foos": {       "type": "hasMany",       "model": "Foo",       "foreignKey": "widgetId"     }   } }  {   "name": "Foo",   ...   "relations": {     "bars": {       "type": "hasMany",       "model": "Bar",       "foreignKey": "fooId"     },     "widget": {       "type": "belongsTo",       "model": "Widget",       "foreignKey": ""     }   } }  {   "name": "Bar"   ...   "relations": {     "foo": {       "type": "belongsTo",       "model": "Foo",       "foreignKey": ""     }   } } 

Results:

{   id: 1   foos: [     {       id: 2,       bars: [         {           id: 3         }       ]     },     {       id: 2,       bars: [         {           id: 3         }       ]     }   ] } 

Expecting:

{   id: 1   foos: [     {       id: 2,       bars: [         {           id: 3         }       ]     }   ] } 

This is paraphrased SQL that I see being run for this request:

SELECT `...` FROM `Widget` WHERE `id`=1 ORDER BY `id` LIMIT 1 SELECT `...` FROM `Foo` WHERE `widget_id` IN (1) ORDER BY `id` SELECT `...` FROM `Foo` WHERE `widget_id` IN (1) ORDER BY `id` SELECT `...` FROM `Bar` WHERE `foo_id` IN (2) ORDER BY `id` SELECT `...` FROM `Bar` WHERE `foo_id` IN (2) ORDER BY `id` 

I'm using Loopback 3.x.

Update: While a request of GET /api/Widgets/1?filter={include: {"foos": "bars"}} exhibits this behavior, a server-side execution of Widgets.findById(id, {include: {"foos": "bars"}}) works perfectly. So, at the moment I'll create a remote method that does this and perhaps file a bug report with LoopBack.

0 Answers

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment