How to query only with included models? - loopbackjs

I have a query that looks like this:
User.find({
include: {
relation: 'Comment',
scope: {
where: {
text: {
like: '%some text'
}
}
}
}
}, function (err, users) {
...
})
Everything works great, but i want to be able to query only the users that commented "some text", like a inner join.
How can i do that?

Related

How to delete cache record from Apollo GraphQL client with readQuery and writeQuery

The Apollo GraphQL team says that readQuery and writeQuery are good for 95% of the use cases. I am using useMutation and update and want to remove an item from a cache without having to call refetchQueries. My code is as follows:
const [deleteSpeaker] = useMutation(DELETE_SPEAKER, {
update(cache, { data: {deleteSpeaker}}) {
const { speakers} = cache.readQuery({query: GET_SPEAKERS});
cache.writeQuery({
query: GET_SPEAKERS,
data: { speakers: speakers.filter(speaker => speaker.id !== deleteSpeaker.id) }
});
},
});
What gets returned from readQuery leads me to think I should be filtering for speakers.datalist but when I do that, the cache does not update.
What is the correct way to update cache to reflect a removed record from the GET_SPEAKERS query.
export const DELETE_SPEAKER = gql`
mutation DeleteSpeaker($speakerId: Int!) {
deleteSpeaker(speakerId: $speakerId) {
id
first
last
favorite
}
}
`;
and GET_SPEAKERS
export const GET_SPEAKERS = gql`
query {
speakers {
datalist {
id
first
last
favorite
company
}
}
}
`;
reading apollo docs, this should be something lke:
const [deleteSpeaker] = useMutation(DELETE_SPEAKER, {
update(cache, { data: {deleteSpeaker}}) {
cache.modify({
id: cache.identify(deleteSpeaker.id),
fields: {
comments(existingSpeakerRefs, { readField }) {
return existingSpeakerRefs.filter(
speaker => deleteSpeaker.id !== readField('id', speakerRef)
);
},
},
});
},
});

How do I make graphql calls in series? react-apollo

I am composing 2 queries in a hoc with react-apollo. Here is my code:
let queries = compose(
graphql(gql`
query getUnitSubcategories($input: UnitSubcategorySearchInput) {
allUnitSubcategories(input:$input) {
edges {
node {
unitSubcategoryId
}
}
}
}
`, {
name: 'subcategories',
options: {
variables: {
input: {
activeFlag: true,
}
}
}
}),
graphql(gql`
query getFinancialTransactions($input: FinancialTransactionLineSearchInput) {
allFinancialTransactionLines(input: $input) {
pageInfo {
total
}
edges {
node {
financialTransaction {
financialTransactionId
}
}
}
}
}
`, {
name: 'financialTransactions',
options: {
variables: {
input: {
unitSubcategories: [
....
]
}
}
}
})
);
You can see that I am getting the unitSubcategories in the first query and they need to be passed to the second query. So I don't want to kick off the second query until I have a result from my first query. What is the best way to do this?
You'll want to use the skip config. See https://www.apollographql.com/docs/react/basics/queries.html#graphql-skip
In your example, you might want to define the skip config in the second query something like this:
{
name: 'financialTransactions',
skip: ({ unitSubcategories }) => !unitSubcategories,
options: ({ unitSubcategories }) => ({
variables: {
input: {
unitSubcategories
}
}
})
}
where you only want the second query to run after you've received the result from the first query. And then use options as a function so you can compute them from props.

How to add nested resolver to schema?

Let's say my query looks like this:
query {
post {
id
user { id, name }
}
}
And resolver map looks like this:
{
Query: {
post: myPostResolverFunc,
}
}
How I can add additional "nested" resolver for post.user?
I tried this but it does not work:
addResolveFunctionsToSchema(schema, {
Query: {
post: {
user: postUserResolveFunc,
},
}
});
You just have to write a resolver for your field. Assuming your schema is something like this :
type Post {
id: ID!,
user: User
}
type User {
id: ID!,
username: String!
}
type Query {
post(id: ID!): Post #assuming you want to request a simple post here
}
You can write resolvers like this :
addResolveFunctionsToSchema(schema, {
Post: {
user(root) {
return getUserById(root.user)
}
}
Query: {
post(root, args, context) {
return getPostById(args.id)
}
}
});

Add Ember Data query helper method

I'm using Ember API with a JSON API backend. The API accepts filters like this:
/users?filter[simple][name]=John
Right now, whenever I want to make a query, I'm doing this:
this.store.query('users', {
filter: {
simple: {
name: 'John'
}
}
});
It would be nice to avoid this verbosity by adding a helper function that works like this:
this.store.simpleQuery('users', { name: 'John' });
That function would pass its arguments directly to query(), just wrapping the query in { filter: { simple: ... } }.
Is this possible? How do I do this?
Well what is stopping you from creating your own method in the adapter to do exactly that?
// ... your adapter code
simpleQuery: function(modelName, query) {
return this.store.query('users', {
filter: {
simple: {
name: 'John'
}
}
});
}
// ...
You need to extend the default store. Add the following to app/services/store.js
import DS from 'ember-data';
export default DS.Store.extend({
simpleQuery(modelName, query) {
return this.query(modelName, {
filter: { simple: query }
});
},
simpleQueryRecord(modelName, query) {
return this.queryRecord(modelName, {
filter: { simple: query }
});
}
});
And you'll be able to do this:
this.store.simpleQuery('users', { name: 'John' });
this.store.simpleQueryRecord('users', { email: 'john#example.com' });

Sencha Touch 2: List and ListItem data fields

I wanted to know how to customize the ListItem content by combining different JSON data fields.
I have three JSON fields: {caption},{subCaption},{source}.
So far, I have been able to use dataMap and use custom classes to wrap additional text and styling around each. However, the only way I have been able to add content is to do so sequentially with the use of apply/update functions. As a result, my ListItems are simply {caption},{subCaption},{source} in their own lines.
Here's how I would like each ListItem to look like:
Combine {caption} and {subCaption} text and create a short story and add this as a panel to the ListItem
Render {source} in a small panel docked at the bottom right of the panel created in step 1.
How can I do the above? The distilled question would be: How can I access and combine the data from different JSON fields and render into ListItem?
My current code for ListItem is copied below for reference.
As always, any help is greatly appreciated! Thanks!
Mohammad
San Jose, CA
Ext.define('qxtapp.view.ResultsListItem', {
extend: 'Ext.dataview.component.ListItem',
requires: [
'qxtapp.view.ResultsListItemCaption'
],
xtype : 'resultslistitem',
alias : 'widget.resultslistitem',
config: {
caption: true,
subCaption: true,
source: true,
dataMap: {
getCaption: {
setHtml: 'caption'
},
getSubCaption: {
setHtml: 'subCaption'
},
getSource: {
setHtml: 'source'
}
},
layout: {
type: 'vbox'
}
},
applyCaption: function(config) {
return Ext.factory(config, qxtapp.view.ResultsListItemCaption, this.getCaption());
},
updateCaption: function(newCaption) {
if (newCaption) {
this.add(newCaption);
}
},
applySubCaption: function(config) {
return Ext.factory(config, Ext.Component, this.getSubCaption());
},
updateSubCaption: function(newSubCaption) {
if (newSubCaption) {
this.add(newSubCaption);
}
},
applySource: function(config) {
return Ext.factory(config, Ext.Component, this.getSource());
},
updateSource: function(newSource) {
if (newSource) {
this.add(newSource);
}
}
});
Ext.define('qxtapp.view.ResultsListItemCaption', {
extend: 'Ext.Component',
applyHtml: function(caption) {
// do some customization to caption and return it
return caption;
}
});
I'm not sure why you need to go through all that trouble, why not use an item template in a simple list?
Ext.define('qxtapp.view.ResultsList', {
extend: 'Ext.dataview.List',
alias: 'widget.resultslist',
config: {
...
itemTpl: new Ext.XTemplate(
"<div class='result-item'>",
"<p class='result-story'>",
"{[this.getStoryHtml(values.caption, values.subCaption)]}",
"</p>",
"<img src='{source}' alt='{caption}' />",
"</div>",
{
// This is a new function on the template created above and can be called
// from within the template html
getStoryHtml: function(caption, subCaption) {
// customize the text to your needs, then return the html to insert
}
}
),
...
}
});
Of course, you would then need to style these items using CSS, but that should be the easy part. ;)