I have a search query which takes an variable and searches based on that.
On my home page I'd like to send this query 3 times with 3 different variables.
But if I do as above I can't get the results.
Here is the query:
const TOP_TEACHER_QUERY= gql`
query topTeachers {
searchBasicTeachersByRating(rating: 3) {
id
name
title
}
searchBasicTeachersByRating(rating: 4) {
id
name
title
isNew
}
}
}
and this is the function
allQueries() {
return this.apollo
.watchQuery<any>({
query: TOP_TEACHER_QUERY,
})
.valueChanges;
}
NOTE :
I have tried adding an interface and define the desired response data, but it has no effect
interface Response {
searchBasicTeachersByRatingMedium: Student[];
searchBasicTeachersByRatingHigh: Student[];
}
allQueries() {
return this.apollo
.watchQuery<any>({
query: TOP_TEACHER_QUERY,
})
.valueChanges;
}
THE DATA IS ONLY CONTAINING A LIST NAMED AFTER THE QUERY (searchBasicTeachersByRating)
I have tried the following query in graphql playground and it returns 2 arrays
but in Angular I can only get one
As a work around I created new queries at back-end, or sent 2 different queries.
But I want a solution for this approach.
Thanks in advance
When a selection set includes the same field multiple times, you need to utilize aliases for the duplicate fields:
searchBasicTeachersByRatingMedium: searchBasicTeachersByRating(rating: 3) {
id
name
title
}
searchBasicTeachersByRatingHigh: searchBasicTeachersByRating(rating: 4) {
id
name
title
isNew
}
After the request completes, each field will be available as a property on data under the provided alias. In the example above, we aliased both fields, but you could omit the alias from one of them.
Related
In Mongoose, I can use a query populate to populate additional fields after a query. I can also populate multiple paths, such as
Person.find({})
.populate('books movie', 'title pages director')
.exec()
However, this would generate a lookup on book gathering the fields for title, pages and director - and also a lookup on movie gathering the fields for title, pages and director as well. What I want is to get title and pages from books only, and director from movie. I could do something like this:
Person.find({})
.populate('books', 'title pages')
.populate('movie', 'director')
.exec()
which gives me the expected result and queries.
But is there any way to have the behavior of the second snippet using a similar "single line" syntax like the first snippet? The reason for that, is that I want to programmatically determine the arguments for the populate function and feed it in. I cannot do that for multiple populate calls.
After looking into the sourcecode of mongoose, I solved this with:
var populateQuery = [{path:'books', select:'title pages'}, {path:'movie', select:'director'}];
Person.find({})
.populate(populateQuery)
.execPopulate()
you can also do something like below:
{path:'user',select:['key1','key2']}
You achieve that by simply passing object or array of objects to populate() method.
const query = [
{
path:'books',
select:'title pages'
},
{
path:'movie',
select:'director'
}
];
const result = await Person.find().populate(query).lean();
Consider that lean() method is optional, it just returns raw json rather than mongoose object and makes code execution a little bit faster! Don't forget to make your function (callback) async!
This is how it's done based on the Mongoose JS documentation http://mongoosejs.com/docs/populate.html
Let's say you have a BookCollection schema which contains users and books
In order to perform a query and get all the BookCollections with its related users and books you would do this
models.BookCollection
.find({})
.populate('user')
.populate('books')
.lean()
.exec(function (err, bookcollection) {
if (err) return console.error(err);
try {
mongoose.connection.close();
res.render('viewbookcollection', { content: bookcollection});
} catch (e) {
console.log("errror getting bookcollection"+e);
}
//Your Schema must include path
let createdData =Person.create(dataYouWant)
await createdData.populate([{path:'books', select:'title pages'},{path:'movie', select:'director'}])
The document says the cache can be automatically updated in the following example:
{
post(id: '5') {
id
score
}
}
mutation {
upvotePost(id: '5') {
id
score
}
}
Would the automatic update work in the following case when the cached object is in a list ? Like this:
This is a query that fetches a list of reviews:
{
reviewList(model:12){
list{
reviewId
text
}
cursor
}
}
When I update one of the reviews from the list to the server, react apollo does not automatically update the cached review:
mutation{
updateReview(reviewId:'1',text:'new text'){
reviewId
text
}
}
Is it a must to use update properties of the mutation component to update the cache?
Assuming you're using apollo-cache-inmemory, unless you are adding an item to or removing an item from the list, it shouldn't be necessary to use update. However, it's important to keep in mind that the cached data is normalized, and that Apollo utilizes the __typename and id (or _id) field to generate the cache key for any queried object. From the docs:
The InMemoryCache normalizes your data before saving it to the store
by splitting the result into individual objects, creating a unique
identifier for each object, and storing those objects in a flattened
data structure. By default, InMemoryCache will attempt to use the
commonly found primary keys of id and _id for the unique identifier if
they exist along with __typename on an object.
If the id field is missing, Apollo won't know how to match up the data from your query and the data from your mutation:
If id and _id are not specified, or if __typename is not specified,
InMemoryCache will fall back to the path to the object in the query,
such as ROOT_QUERY.allPeople.0 for the first record returned on the
allPeople root query. That would make data for given type scoped for
allPeople query and other queries would have to fetch their own
separate objects.
Fortunately, there's a workaround. You can of course just rename reviewId to id on the server side. However, if you want the cache to just use the reviewId field, you can pass in a dataIdFromObject function to your InMemoryCache constructor:
import { InMemoryCache, defaultDataIdFromObject } from 'apollo-cache-inmemory'
const cache = new InMemoryCache({
dataIdFromObject: object => {
switch (object.__typename) {
case 'Review': return object.reviewId
default: return defaultDataIdFromObject(object)
}
}
})
As long as resulting value is unique, you can utilize any other field (or combination of fields) in a similar fashion.
I'm working on a loopback project, I have a model called Depot which has a field likersList, that fiels is an array of string (user id)
I want to find all Depots which has not a specific userId in it's likersList , I tried that filter, but it doesn't work
let userId=req.accessToken.userId;
let filter={
where:{
and:[
....
{likersList:{nin:[userId]}}
]
}
....
}
I also try that {likerList:{neq:userId}} , doesn't work too
But if try this likersList:userId that returns all Depots which has userIdin it's likersList , so I expected that doing {likerList:{neq:userId}} sould do a opposite
All I want is to know how to check if a field (array type) contains a certain value
Help please !
It works here:
It brings all objects that dont contains userId inside the likersList.
let filter={
where: {
{
likersList: {neq: userId}
}
}
}
It brings only objects that contains userId inside the likersList.
let filter={
where: {
{
likersList: userId
}
}
}
What database are you using for your loopback application? I have seen scenarios where nin and inq filter doesn't work for Oracle database. I have used appropriate regular expression filter as a workaround.
This title is quite confusing, but I will try to explain the best that I can. I have a situation where I am collecting and displaying a list of data elements from the server in React Native. It uses a query that sends a GraphQL parameter to the server to limit the initial request to the first 15 elements.
query GetElements ($count: Int) {
elements (count: $count) {
id
name
tye
}
}
As previously stated, this will query the main list with an initial count of 15 elements.
I have another page of the app that a user can create a new element on the backend using a different GraphQL query.
My question is: Is there a way to easily update the main list of elements to include the newly created element without performing any addition network requests? In other words, I want to be able to simply add the new element to the main list of elements whenever the create command is successful.
The problem is: Apollo's readQuery command on the update proxy will not return to me the appropriate data set to update unless I know the variables that were send with the initial query; this includes the pagination count variable.
You can now define the key for the queries cache store like this:
query AllItems($cursor: String, $limit: Int, $query: String) {
items(cursor: $cursor, limit: $limit, query: $query) #connection(key: "AllItemsQuery") {
count
cursor
has_next
has_prior
data{
...CoreItem
}
}
}
if you would just like to receive the added item, it seems like you want subscriptions :: http://dev.apollodata.com/react/subscriptions.html
Normally creating Relay query object for queries with single definition can be done using:
const relayQuery = Relay.QL `
query UserRoute($id_0: ID!) {
user(id:$id_0) {
id,
name,
email
}
}
;
I have query string intercepted from the one that are sent over network. They normally have multiple definitions (eg. query, fragment, mutation, subscription). I want to create a Relay query object for that type of query. The following code throws error:
Relay transform error "You supplied a GraphQL document named 'network' with 2 definitions, but it must have exactly one definition." in file '/Users/ankitshah/lyearnapp/src/network.js'. Try updating your GraphQL schema if an argument/field/type was recently added.
for this code:
const relayQuery = Relay.QL `
query UserRoute($id_0: ID!) {
user(id:$id_0) {
id,
...F0
}
}
fragment F0 on User {
id,
name,
email
}
;
I want this because I want to update Relay Store using Relay.Store.getStoreData().updateQueryPayload(queryObject, payload) function. Any help is appreciated.
I hit the same error. You will need to compact your query to be without fragments like so:
const relayQuery = Relay.QL `
query UserRoute($id_0: ID!) {
user(id:$id_0) {
id,
name,
email
}
}
;
Then it worked.
Try Using namedspaces . Eg
user1 :user(id:$id_0) {
id,
name,
email
}
user2 :user(id:$id_1) {
id,
name,
email
}