Речь идет о добавлении GraphQL к существующему API Java, который принимает несколько списков в качестве входных данных.
Фон:
У меня есть REST API на основе Java getFooInformationByRecognizer
, который принимает список распознавателей, где каждый объект распознавателя содержит идентификатор и его тип, и возвращает информацию, соответствующую каждому идентификатору.
Возможны только 3 типа: A, B или C. Ввод может быть любой комбинацией этих типов.
Например:
[{"id": "1", "type": "A" }, {"id": "2", "type": "B"},{"id": "3", "type": "C"}, {"id": "4", "type": "A"}, {"id":"5", "type": "B"}]
Вот его представление Java:
class FooRecognizer{
String id;
String FooType;
}
Этот API выполняет небольшую обработку. Сначала извлекается весь ввод с идентификаторами типа A и извлекается информация, соответствующая этим идентификаторам. Аналогичным образом извлеките идентификаторы типа B и извлеките информацию, соответствующую этим идентификаторам, и аналогично для C. Итак, он извлекает данные из 3 разных источников и, наконец, сопоставляет их с одной картой и возвращает. Например:
ids of type A --> A SERVICE -> <DATA SOURCE FOR A>
ids of type B --> B SERVICE --> <DATA SOURCE FOR B>
ids of type C --> C SERVICE --> <DATA SOURCE FOR C>
Наконец делает это: Информация A + информация B + информация C и помещает это в хэш-карту Java.
Java-представление запроса к этой службе:
class FooRequest{
private Bar bar;
List<FooRecognizer> list;
}
Java-представление объекта ответа от службы:
class FooInformationResponse{
private Map<String, FooRecognizer> fooInformationCollated;
}
Пример вывода JSON ответа:
"output":{
"fooInformationCollated":{
"1":{
"someProperty": "somePropertyValue"
"listOfNestedProperties": [{"x": "xValue", "y": "yValue", "z","zValue"]
"nestedProperty":{
"anotherProperty":{
"furtherNestedProperty": "value"
}
}
}
"2":{
"someProperty": "somePropertyValue"
"listOfNestedProperties": [{"a": "aValue", "b": "bValue", "c","cValue"]
"nestedProperty":{
"anotherProperty":{
"furtherNestedProperty": "value"
}
}
}
}... and so on for other ids in the input
Теперь я хочу преобразовать этот сервис в GraphQL, и вот мой запрос.
query{
getFooInformationByRecognizer(filterBy:{
fooRecognizer: [{
id: "1",
fooType: A
}],
bar: {
barId: "someId",
...<other bar info>
}
}){
fooInformationCollated{
id
fooInformation{
someProperty
listOfNestedProperties
nestedProperty{
anotherProperty{
furtherNestedProperty
}
}
}
}
}
}
Вот моя схема GraphQL:
type Query{
getFooInfoByRecognizer (filterBy: getFooByRecognizerTypeFilter!):getFooByRecognizerTypeFilterResponse
}
input getFooByIdentifierTypeFilter{
bar: Bar!
fooIdentifiers: [FooIdentifier!]!
}
input Bar{
barId: String!
....
}
input FooIdentifier{
id: String!
fooIdType: fooIdtype!
}
enum fooIdType{
A
B
C
}
У меня есть несколько вопросов:
query getFooInformationByRecognizer(barId, listOfAs, listOfBs, listOfCs)
. Любой другой выбор, который у меня есть для запроса/модели?Вопрос слишком широк, чтобы ответить конкретно, но вот моя лучшая попытка.
Хотя однозначного ответа на вопрос об одном сложном входном аргументе по сравнению с несколькими более простыми аргументами не существует, один сложный аргумент, как правило, предпочтительнее, поскольку клиентам проще передавать одну переменную, а файлы GraphQL меньше. Это может быть более интересно для мутаций, но в любом случае это хорошая эвристика. См. логику, объясняющую это более подробно, например. в этой статье.
Логика, описанная выше, перекликается с вашими собственными наблюдениями.
Для этого конкретного сценария, который вы перечислили, я не вижу ничего важного для производительности. Кажется, вы получаете весь список за один раз (без N + 1), поэтому мало чем отличается от того, что вы делаете для своей конечной точки REST. Теперь я не могу сказать, насколько дорого обходится получение полей более низкого уровня (например, нужны ли вам JOIN или сетевые вызовы или что-то еще), но если есть какая-то нетривиальная логика, вы можете оптимизировать ее, глядя вперед в подвыбор перед разрешением ваших полей верхнего уровня.