Fetch nested items using GraphQL query in JavaScript Amplify - javascript

Definition:
A Team can have many Users and 1 user as manager:
type Team {
id: ID!
title: String
manager: User #connection
users: [User] #connection(name: "TeamUsers")
}
The User type is defined as:
type User {
id: ID!
username: String
team: [Team] #connection(name: "TeamUsers")
}
Using JS, I can access the Team manager's username:
{teams.map((team) => {
return(
<li>{team.manager.username}</li>
)
}
Problem: I can't get the usernames of users in the team using either:
{teams.map((team) => {
return(
<li>{team.users.username}</li>
// or
<li>{team.users.map((user) => {user.username})}</li>
)
}
PS) I am using AWS Amplify and I'm fetching teams using the following code:
const fetchTeams = async () => {
try {
const teamsData = await API.graphql(graphqlOperation(listTeams));
const teamsList = teamsData.data.listTeams.items;
setClients(teamsList);
} catch (error) {
console.error(`fetchTeams failed.`, error);
}
};

As #Bergi said in the comment.
I think
<li>{team.users.map((user) => {user.username})}</li>
=>
<li>{team.users.map(user => user.username)}</li>
will fix your issues

Related

How to push data into subcollections in firebase

I'm creating a messaging app with react-native & firebase. Its working quite alright.
Now i want to take it a step further by creating private chats. To my understanding, i need to populate the data into subcollections. e.g : chats>chatroom1>data, chats>chatroom2>data e.t.c
I'm currently working with this code
import firebase from 'firebase';
class Fire {
constructor (props) {
this.init()
this.checkAuth()
}
init = () => {
if (!firebase.apps.length) {
}
};
checkAuth = () => {
firebase.auth().onAuthStateChanged(user => {
if (!user) {
firebase.auth().signInAnonymously();
}
})
}
send = messages => {
messages.forEach(item => {
const message = {
text: item.text,
timestamp: firebase.database.ServerValue.TIMESTAMP,
user: item.name
}
this.db.push(message)
})
}
parse = message => {
const {user, text, timestamp} = message.val();
const {key, _id} = message
const createdAt = new Date(timestamp)
return {
_id,
createdAt,
text,
user
}
}
get = callback => {
this.db.on('child_added', snapshot => callback(this.parse(snapshot)))
}
off() {
this.db.off()
}
get db() {
return firebase.database().ref("messages");
}
get uid(){
return(firebase.auth().currentUser || {}).uid
}
}
How can I populate the subcollections from this code?
I believe for calling out of specific subcollections, firebase.database().ref("messages/chatroomid"); will do the trick, right?
what i mean by sub collection is this
Currently my JSON tree looks like:
database
- messages
- mvhhsjsfurhcb
- text: "hi"
timestamp: 9942313949
user: "David"
firebase.database().ref("messages"); calls out the data under messages
This is what i want
database
- messages
-chatroom1
- mvhhsjsfurhcb
- text: "hi"
timestamp: 9942313949
user: "David"
-chatroom2
- mvhhsjsfurhcb
- text: "hey, this i room2"
timestamp: 9942313949
user: "Sam"
Then for firebase.database().ref("messages/chatroom1"); to call out only messages in chatroom1.
What I intend to achieve with this is to create a private chat for users
To give you more insight, if I was to do this with PHP, I would be doing SELECT * WHERE chatroom = :chatroom;
i believe the answer will be related to this.db.push(message). maybe adding another '.' indicating that there's another branch before pushing the message
If you want to push the chat message to a specific chat room, you can do:
this.db.child("chatroomid1").push(message)

Nested Query GraphQl

I am new using graphql and I would like to know how could I filter my query to get the recipes that has some of the ingredient objects I have in my input array.
this is the schema.gql file
type Recipe {
id: Int
title: String!
author: String
link: String
category: String
subcategory:String
ingredients:[Ingredients]
}
type Ingredients{
id:Int
name:String!
quantity:Float!
measure:String
observation:String
}
type Query {
recipe: [Recipe]
ingredient:[Ingredients]
}
this recipe schema has 1 respective service
const db = require('../db')
class RecipeService{
//PENDENTE FINALIZAR ESSA SERVICE
async getRecipeByIngredient(ingredient)
}
and the respective Query resolvers
Recipe: {
async ingredients(recipe, _, { dataSources }) {
return await dataSources.IngredientService.getRecipeIngredients(recipe.id)
},
},
Query: {
recipe: async () => db('Recipe'),
ingredient: async () => db('Ingredient'),
}
the main idea here is just to have one filter that can see what recipe has some ingredients that the user will inform via APP.
I got the "recipe" query with all the recipes that I have at the database, but I need a query that get these recipes and filter then using the field ingredient, for example:
Recipe - Sugar Cake with the ingredients: Sugar, Honey, Four...
Recipe - Velvet Cake with the ingredients: Sugar, Vanilla, ...
and the user inform Sugar, the API should return theses 2 recipes, but if the user inform Sugar, Honey and Four, the API would return only the option 1.
can anyone help me on it?
thanks a lot.
I got a solution for this and I would like to share with you.
The filter that I implemented on the resolver:
module.exports = {
Recipe: {
ingredients(recipe, _, { dataSources }, info) {
return dataSources.IngredientService.getRecipeIngredients(recipe.id)
}
},
Query: {
recipe(obj, {name}, {dataSources}, info) {
if (name) {
return dataSources.IngredientService.getIngredientsByName(name)
} else {
return db('Recipe')
}
},
ingredient: async () => db('Ingredient'),
recipeByIngredient:async () => db('Recipe'),
}, Mutation: {
createRecipe: async (_, { data }) => await (await db('Recipe').insert(data).returning('*'))[0],
updateRecipe: async (_, { data, id }) => await (await db('Recipe').where({ id }).update(data).returning('*'))[0],
deleteRecipe: async (_, { filter }) => {
if (filter.id) {
return await db('Recipe').where({ id: filter.id }).delete()
}
if (filter.title) {
return await db('Recipe').where({ title: filter.title }).delete()
}
throw new Error('Should provide the ID or TITLE')
}
}
}
With this resolver module, I created a new filter on the "recipe" Query resolver, that receive the "name" of the ingredient to make the filter and pass it to the Service to implement the filter at the database.
Thanks for the support.

How to use react-native-gifted-chat with cloud firestore?

I am having problem of react-native-gifted-chat by using cloud firestore. I am unable to fetch previous messages and append to the gifted chat. please show me the code that how it is used with the cloud firestore.
thanks
I have been able to get this to work on my app using a similar method to that found at GitHib repo
My code calls a loadMessages function in componentDidMount which uses onSnapshot to keep track of any changes in my Message or Chats collections. If a change occurs it uses a callback function to append the new messages to GiftedChat.
Here is my code:
async componentDidMount() {
this.loadMessages(message => {
this.setState(previousState => {
return {
messages: GiftedChat.append(previousState.messages, message)
};
});
});
}
async loadMessages(callback) {
var that = this;
var recipientId = this.props.navigation.getParam("recipientId");
var chatId = this.generateChatID(recipientId);
this.setState({ chatId });
firebase
.firestore()
.collection("Message")
.doc(chatId)
.collection("Chats")
.orderBy("createdAt", "asc")
.onSnapshot(function(doc) {
doc.docChanges().forEach(chat => {
var id = chat.doc.id;
chat = chat.doc.data();
const newMessage = {
_id: id,
text: chat.text,
createdAt: chat.createdAt.toDate(),
user: {
_id: chat.user._id,
name: chat.user.name,
avatar: chat.avatar
}
};
callback(newMessage);
});
});
}
Lmk if you have any questions!

How can I query a fire store sub-collection with angular?

I am trying to query a Firestore sub collection in an ionic 4 app/angular app. My database looks as follows people(id) ----> tasks(id)
{ description : this is a description about a cat,<br>
title: this is a cat <br>
category: cat }
I am using a Firestore function to query all of the data in the collection. This is what the Firestore function looks like:
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin'
admin.initializeApp()
export const getFeed = functions.https.onCall(async (req,res) =>{
const docs = await
admin.firestore().collection('people').limit(5).get()
return docs.docs.map(doc => {
return {
postID: doc.id,
...doc.data()
}
})
})
the typescript home.ts file looks like this :
const getFeed = this.aff.httpsCallable('getFeed')
this.posts = getFeed({}).subscribe(data=> {
console.log(data)
// this.posts = data
})
}
I've tried to use the array-contains option to query, but it doesn't
work. The array shows up empty on the console.
export const getFeed = functions.https.onCall(async (req,res) =>{
const docs = await
admin.firestore().collection('people').where("category",
"array-
contains", "cat").limit(5).get()
return docs.docs.map(doc => {
return {
postID: doc.id,
...doc.data()
}
})
})
It's not very clear from your question, but it looks like the category field of your database isn't actually a list type field. array-contains only works if the value is a list, not if it's just a single string value. If it's just a string, then use a == filter on it.
I have found workaround by adopting array field type instead of subcollection.
Here is an example of my code:
var coll = this.firestore.collection('credentials', ref => ref.where('tags', 'array-contains-any', ['agile']).orderBy('shortName')); // selects part of collection where roomId = roomStripped, sorted by name
return coll.snapshotChanges();
I have main collection called credentials, and a list of tags in each document.

TypeORM Apollo nested query resolver

I have a schema (with the appropriate database tables and entity classes defined) like
type User {
id: Int!
phoneNumber: String!
}
type Event {
id: Int!
host: User
}
and I'm trying to use Apollo to write a query like
Query{
event(id:1){
host{
firstName
}
}
}
But I can't figure out how to get the Apollo library to resolve the User type in the host field to the hostId that is stored on the event object.
I modified the event to return the hostId field, and it works perfectly fine, but Graphql won't resolve the id to the appropriate user type. What am I missing?
edit: missing resolver code
event: async (parent: any, args: { id: number }) => {
const eventRepository = getConnection().getRepository(Event);
const event = await eventRepository.findOne(args.id);
return event;
},
I managed to get a working version by using findOne(args.id, { relations: ['host']}), but I don't like that because it seems like something that would be appropriate to delegate to graphql to handle.
Your resolver should be like that
const resolver = {
Query: {
event: async (_: any, args: any) => {
return await event.findOne(args.id);
}
},
event: {
host: async (parent: any, args: any, context: any) => {
return await user.find({ id: parent.id });
}
}
};

Categories

Resources