фильтрация секвеста для вложенной модели - PullRequest
0 голосов
/ 25 апреля 2020

Я работал с sequelize в течение нескольких недель, все еще пытаясь научиться ..

Мои модели определены в папке моделей.

/ models / endpoint. js

import Sequelize from 'sequelize';
import { sequelize } from '../data';
import Permission from './permission';

const { Model } = Sequelize;

class Endpoint extends Model { }

Endpoint.init({
  endpoint: {
    type: Sequelize.VIRTUAL(Sequelize.STRING, [ 'method', 'path' ]),
    get() {
      return `${this.get('method')} ${this.get('path')}`;
    }
  },
  method: {
    type: Sequelize.ENUM,
    values: [ 'GET', 'POST', 'PUT', 'DELETE', 'PATCH' ],
    allowNull: false
  },
  path: {
    type: Sequelize.STRING,
    allowNull: false
  },
  description: {
    type: Sequelize.TEXT
  }
}, {
  sequelize,
  modelName: 'endpoint'
});

Endpoint.Permissions = Endpoint.hasMany(Permission);
Permission.Endpoint = Permission.belongsTo(Endpoint, { as: 'permission' });

export default Endpoint;

/ модели / разрешение. js

import Sequelize from 'sequelize';
import { sequelize } from '../data';

const { Model } = Sequelize;

class Permission extends Model { }

Permission.init({
  entity: {
    type: Sequelize.ENUM,
    values: [ '*', 'user', 'extension', 'queue', 'group' ],
    defaultValue: '*'
  },
  role: {
    type: Sequelize.STRING,
    defaultValue: '*'
  }
}, {
  sequelize,
  modelName: 'permission'
});

export default Permission;

найдено что-то в документах: Верхний уровень, где с загруженные модели

User.findAll({
    where: {
        '$Instruments.name$': { [Op.iLike]: '%ooth%' }
    },
    include: [{
        model: Tool,
        as: 'Instruments'
    }]
})

следующим образом, я сделал это

Endpoint.findAndCountAll({ 
  where: { 
    path: { [Symbol(iLike)]: '%user%' },
    '$permissions.role$': { [Symbol(eq)]: 'admin' } 
  },
  include: [ 
    { model: permission, as: 'permissions' } 
  ],
  order: [],
  offset: 0,
  limit: 20 
})

мой код выдает эту ошибку:

Ошибка SequelizeDatabaseError: отсутствует FROM -clause запись для таблицы "разрешения"

и сгенерированный SQL запрос:

SELECT          "endpoint".*, 
                "permissions"."id"           AS "permissions.id", 
                "permissions"."entity"       AS "permissions.entity", 
                "permissions"."role"         AS "permissions.role", 
                "permissions"."createdAt"    AS "permissions.createdAt", 
                "permissions"."updatedAt"    AS "permissions.updatedAt", 
                "permissions"."endpointId"   AS "permissions.endpointId", 
                "permissions"."permissionId" AS "permissions.permissionId" 
FROM            ( 
                       SELECT "endpoint"."id", 
                              "endpoint"."method", 
                              "endpoint"."path", 
                              "endpoint"."description", 
                              "endpoint"."createdAt", 
                              "endpoint"."updatedAt" 
                       FROM   "endpoints" AS "endpoint" 
                       WHERE  "endpoint"."path" ilike '%user%' 
                       AND    "permissions"."role" = 'admin' limit 20 offset 0) AS "endpoint" 
LEFT OUTER JOIN "permissions"                                                   AS "permissions"
ON              "endpoint"."id" = "permissions"."endpointId";

1 Ответ

0 голосов
/ 25 апреля 2020

Не пытайтесь использовать limit и offset с ассоциациями hasMany и findAndCountAll.

Если у вас есть 2 разрешения в каждой конечной точке (например, у вас есть 10 конечных точек и установите LIMIT на 10), тогда вы получите первые 5 конечных точек, потому что в SQL конечные точки запроса будут умножаться с разрешениями.

Если вы все еще хотите фильтровать родительские записи (конечные точки) по некоторым условиям на дочерние записи, тогда я полагаю, что для этой цели вам нужно использовать sequelize.literal.

Если вы хотите отфильтровать родительские и дочерние записи отдельно (и при этом по-прежнему использовать LIMIT и OFFSET), просто переместите условие условия разрешений в предложение ассоциации where а также установить значение: true в ассоциации include, чтобы заставить LIMIT и OFFSET работать правильно (это заставит sequelize выполнить отдельный запрос SQL для получения разрешений для каждой конечной точки. Этот последний случай будет выглядеть следующим образом:

Endpoint.findAndCountAll({ 
  where: { 
    path: { [Symbol(iLike)]: '%user%' }
  },
  include: [ 
    {
     model: permission,
     as: 'permissions',
     separate: true,
     where: {
       role: { [Symbol(eq)]: 'admin' } 
     }
    } 
  ],
  order: [],
  offset: 0,
  limit: 20 
})
...