Я пытаюсь выполнить запрос с агрегацией в Meteor, и я не смог понять, как вернуть запрос агрегации.
В моей схеме GraphQL:
type UserRelation {
date: String!
userID: String!
}
type UserData {
userID: String!
description: String!
friends_list: [UserRelation]!
}
extend type Query {
getFriends(userID: String!, friendID: String): [UserRelation]
}
В моих разрешителях.js:
import UserData from "./userData";
export default {
Query: {
getFriends(obj, args, context) {
if (args.friendID) return UserData.rawCollection().aggregate([
{
$match: {
_id: 'cuS7KebEQDRv2iFpJ'
}
},
{
$unwind: '$friends_list'
},
{
$match: {
'friends_list._id': '8GW4gjwWhkEexfndd'
}
}
]);
return UserData.findOne({ userID: args.userID }, {fields: {_id: 0, friends_list: 1 }}).friends_list;
}
}
}
В этом жестко закодированном примере у меня есть следующий документ в моей базе данных:
И я хочу вернуть весь документ ТОЛЬКО с пользователем с совпадающим _id и в чьем списке друзей есть другой пользователь со вторым совпадающим _id. Таким образом, я могу вернуть весь документ только с одним элементом в массиве friends_list вместо всех остальных элементов.
Теперь этот запрос отлично работает в Robo3T (графический интерфейс MongoDB), но возникает проблема с оператором return, когда я запускаю его в Graphiql, поскольку возникает ошибка, которая гласит:
"Expected Iterable, but did not find one for field \"Query.getFriends\"."
Когда я регистрирую это утверждение, я вижу Mongo AggregationCursor. Но я не уверен, как мне «преобразовать» это в тип, который распознаватель может правильно вернуть.
Любая помощь приветствуется, спасибо!
Нет, это не для findOne, эта часть работает нормально. findOne возвращает весь массив friends_list определенного пользователя. findOne запускается только в том случае, если необязательный аргумент friendID не указан, и в этом случае я возвращаю весь массив friends_list.
просто записывайте данные перед возвратом, проверяйте структуру, сравнивайте с ожидаемыми
Я сделал это, и он показывает AggregationCursor. Я не был уверен, как «преобразовать» это во что-то правильное, но я думаю, что, согласно моему ответу ниже, я, возможно, (?) понял это.
Я не знаю, действительно ли я понял это, потому что мне нужно больше его тестировать, но пока это работает, в моем resolvers.js у меня есть:
import UserData from "./userData";
async function getFriend(userID, friendID) {
return UserData.rawCollection().aggregate([
{
$match: {
_id: userID
}
},
{
$unwind: '$friends_list'
},
{
$match: {
'friends_list._id': friendID
}
}
]).toArray();
}
export default {
Query: {
async getFriends(obj, args, context) {
if (args.friendID){
const result = await getFriend(args.userID, args.friendID);
return result[0].friends_list;
}
return UserData.findOne({ userID: args.userID }, {fields: {_id: 0, friends_list: 1 }}).friends_list;
}
}
}
Сделав это асинхронным, я смог это сделать. Не уверен, какие последствия это имеет, но пока это работает. Если кто-то может просмотреть это и дать некоторую критику, чтобы улучшить это, он был бы искренне признателен, так как любую информацию об этом было мучительно трудно найти, поскольку я до сих пор не видел никаких вариантов использования этого.
findOne не возвращает массив?