Далее, как использовать Op.contains для поиска моделей с определенными значениями - PullRequest
1 голос
/ 17 апреля 2019

Я работаю над проектом по аренде домов и квартир, и я дошел до того, что мне нужно реализовать фильтрацию домов по их функциям (Wi-Fi, охрана и другой персонал). Сначала я решил попробовать Sequelize ORM впервые. Такие вещи, как добавление, создание, редактирование, работают нормально, но с фильтрацией у меня возникают некоторые проблемы.

Я работаю с nodejs, express и postgresql. Мне нужно найти все дома, которые имеют функции, перечисленные в массиве идентификаторов функций. Вот что я попробовал. В этом примере я пытаюсь получить дома, которые имеют особенности с идентификаторами 1, 2 и 4.

db.House.findAll({
  include: [{
    model: db.HouseFeature, 
    as: 'HouseFeatures',
    where: {
      featureId: {
        [Op.contains]: [1, 2, 4] //<- array of featuresIds
      }  
    }
  }]
})

Выбор домов по одному идентификатору функции работает нормально, потому что я не использую там. Вот некоторые отношения, связанные с этим делом:

House.hasMany(models.HouseFeature, { onDelete: 'CASCADE' });
HouseFeature.belongsTo(models.House);

HouseFeature содержит поле FeatureId. Вот ошибка, которую я получаю:

error: оператор не существует: integer @> unknown
       at Connection.parseE (C:\***\server\node_modules\pg\lib\connection.js:601:11)
       at Connection.parseMessage (C:\***\server\node_modules\pg\lib\connection.js:398:19)
       at Socket.<anonymous> (C:\***\server\node_modules\pg\lib\connection.js:120:22)
       at Socket.emit (events.js:182:13)
       at addChunk (_stream_readable.js:283:12)
       at readableAddChunk (_stream_readable.js:264:11)
       at Socket.Readable.push (_stream_readable.js:219:10)
       at TCP.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)
     name: 'error',
     length: 397,
     severity: 'ОШИБКА',
     code: '42883',
     detail: undefined,
     hint:
      'Оператор с данными именем и типами аргументов не найден. Возможно, вам следует добавить явные приведения типов.',
     position: '851',
     internalPosition: undefined,
     internalQuery: undefined,
     where: undefined,
     schema: undefined,
     table: undefined,
     column: undefined,
     dataType: undefined,
     constraint: undefined,
     file:
      'd:\\pginstaller.auto\\postgres.windows-x64\\src\\backend\\parser\\parse_oper.c',
     line: '731',
     routine: 'op_error',
     sql:
      'SELECT "House"."id", "House"."title", "House"."description", "House"."price", "House"."address", "House"."lat", "House"."lon", "House"."kitchen", "House"."bathrooms", "House"."floor", "House"."totalFloors", "House"."people", "House"."area", "House"."bedrooms", "House"."trusted", "House"."createdAt", "House"."updatedAt", "House"."CityId", "House"."ComplexId", "House"."OwnerProfileId", "House"."HouseTypeId", "House"."RentTypeId", "HouseFeatures"."id" AS "HouseFeatures.id", "HouseFeatures"."featureId" AS "HouseFeatures.featureId", "HouseFeatures"."createdAt" AS "HouseFeatures.createdAt", "HouseFeatures"."updatedAt" AS "HouseFeatures.updatedAt", "HouseFeatures"."HouseId" AS "HouseFeatures.HouseId" FROM "Houses" AS "House" INNER JOIN "HouseFeatures" AS "HouseFeatures" ON "House"."id" = "HouseFeatures"."HouseId" AND "HouseFeatures"."featureId" @> \'1,2\';'

Извините за немного русского.

UPDATE:

Мне удалось сделать то, что мне было нужно, изменив каждый дом, относящийся только к одному HouseFeature, и изменив эту модель HouseFeature для хранения массива FeatureIds. Op.contains работает отлично.

  db.House.findAll({
      include: [{
        model: db.HouseFeature, 
        as: 'HouseFeature',
        where: {
          features: {
            [Op.contains]: req.body.features
          }  
        },
      }]     
  })
  // Associations
  HouseFeature.belongsTo(models.House);
  House.hasOne(models.HouseFeature, { onDelete: 'CASCADE' });

  const HouseFeature = sequelize.define('HouseFeature', {
    features: {
      type: DataTypes.ARRAY(DataTypes.INTEGER)
    }
  }, {});

Теперь у меня есть одна маленькая проблема. Могу ли я каким-либо образом связать модель HouseFeature с моделью объектов для получения изображений значков объектов и их имени в дальнейшем? С идентификаторами объектов, хранящимися в массиве HouseFeature.

1 Ответ

0 голосов
/ 17 апреля 2019

Пожалуйста, проверьте разницу между Op.in и Op.contains:

[Op.in]: [1, 2], // IN [1, 2]

[Op.contains]: [1, 2] // @> [1, 2] (PG array contains operator)

Похоже HouseFeatures.featureId - это ПК типа integer, а не postgres array.

. Попробуйте:

db.House.findAll({
  include: [{
    model: db.HouseFeature, 
    as: 'HouseFeatures',
    where: {
      featureId: {
        [Op.in]: [1, 2, 3]
      }  
    }
  }]
})

или даже

db.House.findAll({
  include: [{
    model: db.HouseFeature, 
    as: 'HouseFeatures',
    where: {
      featureId: [1, 2, 3]
    }
  }]
})

вместо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...