2016-02-08 1 views
1

Вот моя ситуация:Sequelize.js - Как создать нетривиальные ассоциации без необработанного SQL?

Я использую Postgres 9.4, Sequelize ОРМ и имеют следующие модели:

  • Сервис

    • serviceCode - первичный ключ, строка из 6 символов
    • serviceTitle - строка
  • ServiceGroup

    • serviceCodePrefixes - массив строк, которые префиксы для Service.serviceCode
    • serviceGroupTitle - строка
  • Задача

    • serviceCode - ссылка Сервис

Мне нужно создать объект Task, заполненный объектами Service и ServiceGroup. Пример:

In database: 
Service { 
    serviceCode: '123232', 
    serviceTitle: 'svc title #1', 
} 

ServiceGroup { 
    serviceCodePrefix: ['12', '13', '92', ...], 
    serviceGroupTitle: 'svc grp title #1', 
} 

Task { 
    serviceCode: '123232', 
} 

Result: 
Task { 
    service: { 
    serviceTitle: 'svc title #1', 
    }, 
    serviceGroup: { 
    serviceGroupTitle: 'svc grp title #1', 
    }, 
} 

Проблема состоит в том, что serviceCodePrefix содержит не простые идентификаторы, которые могут быть использованы для создания ассоциации с использованием hasOne/belongsTo/и т.д., но префикс для ID..

Так что вопросы: как это можно сделать без необработанного sql?

ответ

1

Оказывается, что прямо сейчас Sequelize имеет экспериментальную функцию: опция 'on' для 'include'. Этот параметр позволяет пользователям настраивать условия соединения. Таким образом, моя проблема может быть решена следующим образом:

const Service = sequelize.define('service', { 
    serviceTitle: Sequelize.STRING, 
    serviceCode: Sequelize.STRING, 
}); 

const ServiceGroup = sequelize.define('service_group', { 
    serviceGroupTitle: Sequelize.STRING, 
    // Array of prefixes (e.g. ['01%', '023%']) 
    serviceCodePrefix: Sequelize.ARRAY(Sequelize.STRING), 
}); 

const Task = sequelize.define('task', { 
    taskTitle: Sequelize.STRING, 
    serviceCode: Sequelize.STRING, 
}); 

Task.belongsTo(Service, { foreignKey: 'serviceCode' }); 

// Hack needed to allow 'include' option to work 
Task.hasMany(ServiceGroup, { foreignKey: 'serviceCodePrefix', constraints: false }); 

// And finally 
Task.findAll({ 
    include: [ 
    { model: Service }, 
    { 
     model: ServiceGroup, 
     on: [' "task"."serviceCode" LIKE ANY("serviceGroup"."serviceCodePrefix") '], 
    }, 
    ], 
}); 

Не уверен в производительности.

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