2017-02-01 2 views
6

Когда я запрашиваю, чтобы включить вложенную модель - например. GET /api/Widgets/1?filter={include: {"foos": "bars"}} - Я получаю дубликат foos в результатах поиска. Я думал, что это связано с LEFT JOIN или что-то в этом роде, поскольку я использую MySQL, но когда я запускаю LoopBack в режиме отладки loopback:connector:mysql, я вижу, что запрос для начального виджета выполняется один раз, но запрос для foo выполняется дважды, а запрос для строки запускается дважды. Почему такое поведение происходит, и что я могу изменить (мои модели, мой код или мои ожидания)?Почему это вложенное отношение в LoopBack возвращает повторяющиеся результаты?

Модели:

{ 
    "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": "" 
    } 
    } 
} 

Результаты:

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

Ожидая:

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

Это перефразировать SQL, что я вижу, выполняющиеся для этого запроса:

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` 

Я использую Loopback 3.x.

Update: Хотя запрос о GET /api/Widgets/1?filter={include: {"foos": "bars"}} экспонатов этого поведения, выполнение с сервера стороне Widgets.findById(id, {include: {"foos": "bars"}}) прекрасно работает. Итак, на данный момент я создам удаленный метод, который сделает это, и, возможно, представит отчет об ошибке с помощью LoopBack.

+1

Если он отлично работает при выполнении на стороне сервера, и вы просто получаете дубликаты через вызовы API, то, возможно, есть проблема с [маршрутами Loopback] (https://loopback.io/doc/en/lb3/Routing. HTML); двойной вызов или некоторые вложенные маршруты могут вызвать эту проблему. –

+0

Вы решаете это? – Casy

+0

См. Мой ответ @Casy, это может помочь вам в правильном направлении, если вы столкнулись с подобной проблемой. Спасибо, Кристос, это помогло мне разобраться. –

ответ

0

Я использовал this mixin, что ограничивает limit от запроса до максимального на определенный стоимость. Когда include присутствует в запросе, Mixin также устанавливает ограничение на сферу действия включают в себя как так:

"include": {"foo":"bar","scope":{"limit":1}}

Кажется, что Mixin предполагал, все включает в себя, что объекты будут записаны в виде {"relation":"foo", "scope":{"include:"bars"}} ,

1

Вы пытались удалить следующие строки? Поскольку по умолчанию, если foreignKey НЕ установлен, он устанавливает его как <relationName>Id. Но поскольку вы устанавливаете его в пустую, loopback не ищет какой-либо столбец для ссылки. следовательно, он получает все записи на вашей родственной модели.

{ 
    "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": "" // remove this 
    } 
    } 
} 

{ 
    "name": "Bar" 
    ... 
    "relations": { 
    "foo": { 
     "type": "belongsTo", 
     "model": "Foo", 
     "foreignKey": "" //remove this 
    } 
    } 
} 

UPDATE:

Это, как я называю 2-го (или 3-го) уровня отношений:

/api/Widgets/1?filter={include: [{"relation":"foo", "scope":{"include:"bars"}}]} 
+0

Это, похоже, не имеет значения. По умолчанию foreignKey вычисляется как 'отношениеName + 'Id'', является ли строка пустой или опущена. –

+0

обновил мой ответ. Добавлено, как я называю отношения третьего уровня. –

+1

Это полезно, Марк. Я считаю, что mixin, который я использовал, вызвал эту проблему, предполагая, что все многоуровневые отношения были определены следующим образом. –

Смежные вопросы