Loopback get filtered result in the same order - loopbackjs

I have two loopback model like
Model1
{
"id":"",
"name":"",
"model2Ids":[]
}
This model has an array of model 2 ids using the referencesMany relation.
I want to query Model from the remote method of model 1.
My remote method is as follows
Model1.customRemoteMethod = function(id, cb) {
var Model2 = Model1.app.models.model2;
Model1.findById(id, function(model1Error, model1Obj) {
if (model1Error) cb(model1Error);
if (model1Error.model2Ids) {
var model2Filter = {
'where': {
'id': {'inq': model1Obj.model2Ids}
}
};
Model1.find(model2Filter, function(model2Error, model2s) {
if (model2Error) cb(model2Error);
cb(null, Object.assign({}, JSON.parse(JSON.stringify((channelMapObj))), {
model2s: model2s
}));
});
}
})
})
I want the models that are returned(that is the filtered results) to be in the same array as that of my ids in Model1.Is there a way to do it.?
For example if I query using id 2,1,3.
Then the results should be the same order and not 1,2,3(as found in model 2).
The only solution that I have would be to loop over the id, and the use findById to get all results in same order.

Related

How to redefine shape of query in Apollo GraphQl after a response

Working with apollo is great but how can you change the shape of the response from a query. I am using reactjs to display user details and their music information
Say I have a query
query {
userDetails {
id,
name,
music {
name,
type
}
}
is there a way to change the shape using apollo (not in reactjs) to something like
query {
userDetails {
id,
name,
musicName,
musicType
}
}
so that I get the second shape as the response rather than the first, then which I will have to change it using reactjs
You can create local-only fields that reads from the fetched fields by using the #client-directive and TypePolicies
Assuming the typename returned from the query is "User":
Query:
query {
userDetails {
id,
name,
music {
name,
type
}
musicName#client
musicType#client
}
Client setup:
const client = new ApolloClient({
cache: new InMemoryCache({
typePolicies: {
User: {
fields: {
musicName: {
read(_, { readField }) {
return readField('music').name;
}
},
musicType: {
read(_, { readField }) {
return readField('music').type;
}
},
}
}
}
}),
uri: "yourGraphqlServer.com"
});

Adonis.js - Seeding Users and Profiles throwing DB error (Postgres)

I am trying to write a seed file for users and profiles with a one to one relationship and currently getting an "error: relation 'user_profiles' does not exist". From digging around, it seems like Adonis will assume this as a pivot table in the case of a many to many relationship. What I (think or intend to) have is a one to one relationship between users and profiles. Thanks in advance! Newbie to SQL and Adonis. As a side note, the user persists to the db, but there is no corresponding profile.
// My User Schema
class UserSchema extends Schema {
up () {
this.create('users', (table) => {
table.increments('id')
table.string('username', 80).notNullable().unique()
table.string('email', 254).notNullable().unique()
table.string('password', 60).notNullable()
// table.integer('profile_id').unsigned().references('id').inTable('userprofiles')
table.timestamps()
})
}
down () {
this.drop('users')
}
}
// My Profile Schema
class UserprofileSchema extends Schema {
up () {
this.create('userprofiles', (table) => {
table.increments()
table.string('first_name')
table.string('last_name')
// table.integer('user_id')
// .unsigned().references('id').inTable('users')
table.integer('user_id')
.unsigned()
.index('user_id')
table.foreign('user_id')
.references('users.id')
table.timestamps()
})
}
down () {
this.drop('userprofiles')
}
}
My User model includes the following relationship definition:
profile () {
return this.hasOne('App/Models/UserProfile')
}
// Seed script
class UserSeeder {
async run () {
try {
const user = await Factory.model('App/Models/User').create()
const userProfile = await Factory.model('App/Models/UserProfile').make()
userProfile.user_id = user.id
await user.profile().save(userProfile)
} catch (e) {
console.log('Error From Seeder: ', e);
}
}
}
Error code '42P01' and can post whole body if needed. Thanks!
On your Model userProfile, set table name as follows.
class User extends Model {
static get table () {
return 'userprofiles'
}
}

Invariant Violation error when updating apollo cache after mutation

I try update my list after item remove by this article
but get Invariant Violation error.
my mutation:
const deleteFn = useMutation<FeaturedPlaylistGroupDelete, FeaturedPlaylistGroupDeleteVariables>(deleteQuery, {
update: (cache, mutationResult) => {
console.log('mutationResult', mutationResult)
const data = cache.readQuery({ query: featuredPlaylistsGroupsQuery })
console.log('cache', cache)
console.log('cacheData', data)
cache.writeQuery({
query: featuredPlaylistsGroupsQuery,
data: data.filter((item) => item.id !== mutationResult.data.featuredPlaylistGroupDelete.id),
})
},
})
featuredPlaylistsGroupsQuery:
export const featuredPlaylistsGroupsQuery = gql`
query FeaturedPlaylistGroups(
$active: Boolean
$noCategory: Boolean
$dateFrom: String
$dateTo: String
$title: String
$regions: [String!]
$categories: [String!]
) {
featuredPlaylistGroups(
active: $active
noCategory: $noCategory
dateFrom: $dateFrom
dateTo: $dateTo
regions: $regions
title: $title
categories: $categories
) {
active
category {
title
}
datetime
id
region
title
}
}
`
deleteQuery:
const deleteQuery = gql`
mutation FeaturedPlaylistGroupDelete($id: String!) {
featuredPlaylistGroupDelete(id: $id) {
active
categoryId
category {
title
}
datetime
id
region
title
}
}
`
error:
Invariant Violation: Can't find field
featuredPlaylistGroups({}) on object {
...
When you use readQuery, what's returned is what would have been returned in the data part of the response for that query. This is always an object. So for a query like
query {
foo
bar
}
You get an object like
{
"foo": "FOO",
"bar": "BAR"
}
When you call readQuery using your featuredPlaylistsGroupsQuery, you'll get an object with a single property named featuredPlaylistGroups. So your code should look more like:
const cached = cache.readQuery({ query: featuredPlaylistsGroupsQuery })
const featuredPlaylistGroups = cached.featuredPlaylistGroups.filter(item => {
return item.id !== mutationResult.data.featuredPlaylistGroupDelete.id
})
const data = {
...cached,
featuredPlaylistGroups,
}
cache.writeQuery({
query: featuredPlaylistsGroupsQuery,
data: data,
})
However, this still will not work because featuredPlaylistsGroupsQuery takes a number of variables. We need those variables in order to read and write from the cache, since each combination of variable that has been queries is stored separately in the cache. So you will either need to keep track of the variables used and call readQuery/writeQuery on all used combinations, or use something like apollo-link-watched-mutation

How to access data of another persisted model of loopback from remote method of one persisted model?

'use strict';
module.exports = function (City) {
City.GetCurrentPopulation = function (req) {
var population;
City.app.models.Pupulation.find({where{id:req.id}}, //This line //gives me an error that cannot read property 'find' of undefined
function(req.res){
population=res.population;
});
response='Population for ' +req.cname ' is' +population;
req(null, response);
};
City.remoteMethod(
'GetCurrentPopulation', {
http: {
path: '/GetCurrentPopulation',
verb: 'GetCurrentPopulation'
},
returns: {
arg: 'startdate',
type: 'string'
}
}
);
There is a model city and i want to access another model like "population.find(some filters)" How to do this?
I have a remote method written in city model. Where i am trying to access population record as
var countryp=population.find(where{id:4});
var currentpopulation=countryp.Totalpopulation;
It gives an error population.find is not a function.
Please suggest way to do this.
City.app.models.Population can only work if you defined some relation between City & Population models. Otherwise it wont work that way. If there is no relation to the other model. You need to get a reference to the app object using
Try like this:
var app = require('../../server/server');
module.exports = function (City) {
var Population = app.models.Population;
City.GetCurrentPopulation = function(req) {
Population.find({where{id:req.id}}, function (err) {
if (err) {
return console.log(err);
} else {
// do something here
});
}
You can refer to the documentation here https://loopback.io/doc/en/lb3/Working-with-LoopBack-objects.html#using-model-objects

How to commit related models

I'm working with ember-pre4 and ember-data rev 11.
Models:
A = DS.Model.extend({
//some other fields
b: DS.hasMany('B')
})
B = DS.Model.extend({
//some other fields
a: DS.hasOne('A')
})
In my router I create an instance of model A and create an instance of model B and connect them. They both don't have server-side id. Something like this:
var a = A.createRecord();
b = B.createRecord();
b.set('a', a)
a.get('b').addObject(b)
When I want to save those models I make:
a.transaction.commit()
And I expected to see:
Save a with empty b // []
After saving a pass a's id into b and save b
After saving b refetch a
But unfortunately ember does 2 request in parallel and a's request data is:
"{//some fields, b: [/url_to_b//]}" // we dont have b's id
b's request data is:
"{//some fields } // we dont have a's id
What is the best way to solve this problem, does new ember have a default solution for my situation or I should do all stuff manually?
Solution:
I wrapped createRecord function in waitForParents function:
waitForParents:function (record, callback, context) {
var observers = new Em.Set();
record.eachRelationship(function (name, meta) {
var relationship = get(record, name);
if (meta.kind === 'belongsTo' && relationship && get(relationship, 'isNew')) {
var observer = function () {
relationship.removeObserver('id', context, observer);
observers.remove(name);
finish();
};
relationship.addObserver('id', context, observer);
observers.add(name);
}
});
finish();
function finish() {
if (observers.length === 0) {
callback.call(context);
}
}
},
createRecord:function (store, type, record) {
this.waitForParents(record, function () {
// createRecord code here
}
}