Как написать разрешающие фильтры graphql на сервере apollo graphql

Требование:

Мне нужна рекомендация по написанию функции распознавателя для обработки фильтров graphql. Фильтр поддерживает операторы eq, ne, like, contains и not like.

Схема:

import { gql } from 'apollo-server-express';

export default gql`
   extend type Query {
       authGroups(filter: AuthGroupFilterInput): AuthGroupConnection!
    }

    type AuthGroup implements Node {
       id: ID!
       name: String
    }

    input AuthGroupFilterInput {
       name: StringFilterInput
    }

    type AuthGroupConnection {
       edges: [AuthGroup!]!
       pageInfo: PageInfo
    }

    input StringFilterInput {
      lt: String,
      gt: String,
      eq: String,
      ne: String,
      contains: String,
      like: String,
      notLike: String,
    }  

`;

Запрос GraphQL:

 Query {
    authGroups(filter: {  
          name: {
             like: '%AD'
          }
       }
      )
    {
       edges {
         id
         name
       }
    }
 }

Резольверы:

authGroups: async (parent, args, { models }) => {
        const filter = args.filter;
        const filters = filter 
                        ? {
                            where: filter,
                        } 
                        : {};

        const authGroups = await models.authGroup.findAll({
           ...filters
        //    where : {
        //        name: {
        //            [Sequelize.Op.like] : 'AD%'
        //        }
        //    }
        });  
}

Используемые технологии:

  • Сервер Apollo
  • выражать
  • Продолжить
  • PostgreSQL

Как заменить операторы в фильтре на [Sequelize.Op.operator]? Я пробовал использовать operatorAliases в config.json, но это не дало никакого эффекта. Ваша помощь очень ценится.


person RajKrishnan    schedule 21.02.2019    source источник


Ответы (2)


Вы можете просто использовать скобки для доступа к правильному свойству на Op. Что-то вроде этого:

function transformFilter (filter) {
  for (const fieldName in filter) {
    const condition = filter[fieldName]
    filter[fieldName] = {}
    for (const operatorName in condition) {
      filter[fieldName][Op[operatorName]] = condition[operatorName]
    }
  }
}

Обозначение скобок работает даже тогда, когда оно "вложено" как это.

person Daniel Rearden    schedule 21.02.2019
comment
Мой ноутбук разбился, и я занимаюсь восстановлением данных. Я вернусь к вам после того, как попробую это решение. - person RajKrishnan; 25.02.2019
comment
Эта функция сработала для меня, и я предпочитаю этот подход, поскольку операторы не рекомендуется. Как расширить эту функцию для поддержки оператора ИЛИ? - person RajKrishnan; 07.03.2019
comment
Добавление операторов типа and или or потребует гораздо более сложной логики. Фактически, это, вероятно, потребует от вас пересмотра того, как вы настроили свою схему. Это действительно выходит за рамки этого вопроса. Взгляните на как это делает Graphcool. для некоторых идей. - person Daniel Rearden; 07.03.2019

Я решил эту проблему с помощью OperatorAliases, передав ее в конструктор Sequelize.

import Sequelize from 'sequelize';
const operatorsAliases = {
    eq: Op.eq,
    ne: Op.ne,
    gte: Op.gte,
    gt: Op.gt,
    lte: Op.lte,
    lt: Op.lt,
    ......
}

Используйте эти псевдонимы в продолжении при подключении.

const dbService = {
    connect: (host, database) => {
        const sequelize = new Sequelize(
            database,
            user,
            pwd, {
                host: host,
                dialect: 'yourDialect',
                dialectOptions: {
                    domain: domain,
                    encrypt: true
                },
                operatorsAliases: operatorsAliases,
                pool: {
                    max: 100,
                    min: 10,
                    idle: 200
                }
            }
        );

        sequelize
            .authenticate()
            .then(() => {
                console.log(database, 'Connection has been established successfully.');
            })
            .catch((err) => {
                console.error(err, `Unable to connect to the database.`);
            });

        return sequelize;
    }
};
const yourDBRef = dbService.connect(hostName, dbName);

И он должен работать прямо в вашем резольвере без каких-либо дополнительных усилий.

  const authGroups = await models.authGroup.findAll({
        where :filters
    }); 
person Amit Bhoyar    schedule 21.02.2019
comment
Мой ноутбук разбился, и я занимаюсь восстановлением данных. Я вернусь к вам после того, как попробую это решение. - person RajKrishnan; 25.02.2019
comment
Спасибо, Амит, это решение сработало и для меня. Я сделал ошибку при определении операторов в файле конфигурации. Я переместил операторы в то место, где создается экземпляр sequelize, и это сработало. - person RajKrishnan; 07.03.2019