#merge #graphql #aggregation #graphql-java
#слияние #graphql #агрегация #graphql-java
Вопрос:
У меня есть набор функций на стороне сервера, каждая из которых возвращает список объектов одного и того же типа на основе переданных параметров преобразователям в запросе GraphQL-
query {
objListQuery {
objResolver1(params) {
obj-id
}
objResolver2(different params) {
obj-id
}
...
}
}
Здесь objResolver1 и objResolver2 отправляют обратно список объектов obj.
На стороне сервера —
function objResolver1(params) -> returns list of obj
function objResolver2(different params) -> returns list of obj
...
Я хочу выполнить логическое И между результатами преобразователей, то есть найти общие объекты в результатах разных преобразователей.
Вместо получения отдельных списков мне нужен только объединенный список.
Одним из способов является объединение результатов на стороне клиента, но это увеличит объем дублированных данных, отправляемых сервером.
Каков наилучший способ добиться этого на стороне сервера? Какие изменения требуются в схеме?
———————РЕДАКТИРОВАТЬ———————
Источником данных является массив OBJ объектов в формате JSON, который получается из внешней службы на сервере. Источник данных не является базой данных.
Параметров в каждом преобразователе может быть один или несколько. Используется для фильтрации объектов. Например, хранилище данных будет иметь структуру как:
[
{"dateCreated":"2011-08-12T20:17:46.384Z",
"type":"customer",
....
},
{"dateCreated":"2011-08-14T20:17:46.384Z",
"type":"test",
....
}
]
преобразователи будут иметь вид:
dateResolver(String StartDate, String EndDate) -> возвращает список объектов, дата создания которых находится в пределах диапазона typeResolver(String[] type) -> возвращает список объектов, тип которых является любым из значений, переданных в массиве.
Комментарии:
1. агрегируйте схему в единую схему и вызывайте каждый из револьверов внутри этой агрегированной схемы
2. Существует несколько способов сделать это, наиболее подходящий для вас будет основан на точном характере извлекаемых данных. Можете ли вы уточнить схему, например, что делают два разных преобразователя? И чем отличаются параметры?
3. @dazardous добавил пример использования.
Ответ №1:
Предполагается, что вы используете базу данных, которую вы каким-то образом спрашиваете, как перенести ограничения с уровня базы данных или хранилища на уровень контроллера.
Хотя, возможно, это имеет некоторую слабость на уровне модели, это может зависеть от реализации класса, если вы можете легко изменить objResolver
вид, который вы только что создали, который допускает больше параметров, подобных этому:
query {
objListQuery {
objResolver(params1, params2, constraint) {
...
}
}
}
Таким образом, вы можете создать запрос к базе данных, который напрямую извлекает правильный результат, или вы можете выполнить несколько запросов и разрешить их внутри objResolver
. Если constraint
всегда AND
, вы можете оставить параметр подальше, но, возможно, вам нравится предлагать возможность использовать также OR
, XOR
, или другие.
Если количество наборов параметров всегда равно 2, то это просто, как мой приведенный выше код, также учитывая необязательное ограничение. Если количество наборов параметров может быть переменным, т. Е. 4 или 5, то это усложняется, если вы все еще хотите предложить параметр (ы) ограничения. Без ограничений-параметров все просто, вы просто можете отметить функцию без параметров, но проверить количество параметров в вызывающем объекте и обработать их соответствующим образом, в вызывающем объекте вы просто используете столько параметров, сколько требуется.
query {
objListQuery {
objResolver() {
paramArray = getArguments();
}
}
}
Как написано выше, становится сложно, если вы все еще хотите предложить здесь параметры ограничений, но я бы предположил, что это будет материалом для другого вопроса.
Комментарии:
1. Несколько параметров могут принадлежать одному преобразователю. Это приведет к тому, что список параметров в объединенном преобразователе будет очень большим, и порядок параметров будет трудно поддерживать. Кроме того, что делать, если один из преобразователей не должен использоваться для конкретного случая? Затем в объединенном преобразователе должны быть переданы нулевые значения.
2. Кроме того, источником данных является массив JSON, а не база данных.
3. Даже если все ваши варианты использования могут быть известны, потребуется некоторое время, чтобы все прошло гладко, но, возможно, вы можете объяснить, что вы имеете в виду, говоря «если один из преобразователей не должен использоваться для конкретного случая», и если вы всегда используете 1 или 2 параметра или более, если хотитепредлагать ограничения и т. Д. Без подробного знания ваших потребностей трудно ответить подробно.
Ответ №2:
Вы можете реализовать интерфейс подключения с одним преобразователем, чтобы обеспечить одноэтапный механизм запроса. Вы можете уменьшить конечные точки запроса, используя этот метод.
Например, пример запроса будет выглядеть так:
allObjects(start: "01-01-2019", end: "04-29-2019", types:["test", "sales"]){
nodes {
id,
dateCreated,
type
}
}
В преобразователе вы можете использовать этот критерий для подготовки и возврата данных.
Преимущества:
- Меньше конечных точек запроса.
- Фильтрация и разбивка на страницы.
Ваш интерфейс фильтра может быть довольно причудливым:
allObjects(
dateCreated: {
between:{
start,
end
},
skipWeekends: true
},
types: {
include:[],
exclude: []
}
)
- Добавляйте новые критерии по мере роста ваших потребностей. Начните с того, что вы хотите, и возьмите это оттуда.