AdonisJs nested relationships - adonis.js

Have try to create and nested relation with adonisjs.
Invoice -> hasMany -> InvoiceDetails -> belongsTo -> product
This is the Laravel query that works!
Invoice::with('invoiceDetails.product')->get();
These are my relations
Invoice Model
#hasMany(() => InvoiceDetail,{foreignKey: 'invoice_id'})
public invoiceDetails: HasMany<typeof InvoiceDetail>
InvoiceDetails Model
#belongsTo(() => Product,{foreignKey: 'product_id'})
public product: BelongsTo<typeof Product>
Invoice Controller
const invoice = await Invoice.query().preload('invoiceDetails').where('id', request.param('id')).firstOrFail();
How to solve this?

I found the solutions.but i don't know about the solutions is best.
there is my solutions
const invoice = await Invoice
.query()
.preload('invoiceDetails', (profileQuery) => {
profileQuery.preload('product')
})
.where('id', request.param('id'))
.firstOrFail();

Related

How to search items in AWS Amplify Datastore?

In my react native app with AWS amplify backend I want to search 'product' model.
At the moment I'm doing it like this first I query all the products like this
useEffect(() => {
const getallProducts = async () => {
await DataStore.query(Product).then(setAllProducts);
};
getallProducts();
}, []);
Then I filter these products to show the search results to the User.
But I want to implement this search function without querying all products to the device. How can I do this?

How should be the schema on relations between microservices

I'm using NestJS + Prisma + Apollo Federation.
On microservice A is the definition of user, on microservice B is defined posts.
The relation is 1 - N, a user can have N posts.
In Prisma, datamodel of Post is defined with a String for user, since userId is a uuid.
type Post {
id: Int! #id
createdAt: DateTime! #createdAt
updatedAt: DateTime! #updatedAt
user: String!
}
In generated schema (with https://graphql-code-generator.com), Post has a attribute of type User, and this type User extends the id and a array of posts:
type Post #key(fields: "id") {
id: Int!
createdAt: DateTime!
updatedAt: DateTime!
user: User!
}
extend type User #key(fields: "id") {
id: ID! #external
posts: [Post]
}
In apollo federation, all works as expected, except when a query is made trying to link between both microservices.
On playground, if you try to query posts with its user without setting subfields, it breaks the schema and say you have to set the subfields of User, and if you set the subfields graphql responds with a message that you cannot use subfields because its type is String.
The only way that I could make this work correctly was setting in Prisma a userId field of type string and setting another field in schema called user of type User. But all the examples didn't show a field to work with db and a field to work with schema.
My question is if that is the recommended or am I missing something.
In order to get User from Post, you have to create a resolver in your post and user service.
Post Service
const resolvers = {
Post:{//before you do this you have to extend User schema which you already did.
// you are basically asking the 'User' service, which field should be used to query user.
user: ref => ({ __typename: 'User', id: ref.userId })
}
Query:{
// query resolvers
},
Mutation:{
// mutation resolvers
}
User service
const resolvers = {
User:{//the code below allows other services to extend User in their own schemas
__resolveReference: (ref, { userDataLoader }) => userDataLoader.load(ref.id),
}
Query:{
// query resolvers
},
Mutation:{
// mutation resolvers
}
Now linking arrays like [Post] must be done purely in the post service
Post Service
const resolvers = {
Post:{//before you do this you have to extend User schema which you already did.
// you are basically telling the user service, which field should be used to query user.
user: ref => ({ __typename: 'User', id: ref.user })
},
User:{
posts:(ref, args, {postDataLoader}) => getOrders(ref.postIds) //or ref.userId(foreign key)
},
Query:{
// query resolvers
},
Mutation:{
// mutation resolvers
}

Active Model Serializer with Ember - how to add an element to the collection

I have 2 models Country and Language linked with HABTM relation.
I'm using Rails API with ActiveModelSerializer and Ember JS as frontend.
So how is it possible to add a new language to country.languages collection ?
On the Ember side I'm trying to add a new language as follows:
#router
actions: {
saveLanguage(language) {
let controller = this.get('controller');
let country = controller.get('aCountry');
country.get('languages').pushObject(language);
country.save();
}
}
This calls CountriesController#update action in Rails.
Here is how I deserialize params hash in Rails controller:
#countries_controller.rb
def country_params
ActiveModelSerializers::Deserialization.jsonapi_parse!(params)
end
And here is what it returns:
{:code=>"BE", :name=>"BELGIUM", :modified_by=>"XXX", :id=>"5", :language_ids=>["374", "231", "69"]}
So I'm getting all I need:
country ID => id=5
languages IDS => both existing ones (2) and a new one.
How to properly update the country ? Thank you.
I figured out hot to add/delete an item to/from a association.
So on Ember side it looks like that:
actions: {
deleteLanguage(language) {
let controller = this.get('controller');
let country = controller.get('aCountry');
country.get('languages').removeObject(language);
country.set('modifiedBy', this.get('currentUser.user').get('username'))
country.save();
},
saveLanguage(language) {
let controller = this.get('controller');
let country = controller.get('aCountry');
country.get('languages').pushObject(language);
country.set('modifiedBy', this.get('currentUser.user').get('username'))
country.save();
}
And on the Rails side everything happens in the CountriesController:
class CountriesController < ApplicationController
...
def update
if #country.update(country_params)
json_response #country
else
json_response #country.errors, :unprocessable_entity
end
end
private
def find_country
#country = Country.includes(:languages).find(params[:id])
end
def country_params
ActiveModelSerializers::Deserialization.jsonapi_parse!(params,
only: [
:id,
:modified_by,
:languages
])
end
end
Sure, I'll have to add some errors handling on Ember side just to display a confirmation of the update or the errors.
Method json_response is just my custom helper defined as follows in concerns for controllers:
module Response
def json_response(object, status = :ok, opts = {})
response = {json: object, status: status}.merge(opts)
render response
end
end
Hope this helps. You can find more about mode relations in Ember Guide.

AdonisJS no default values for timestamps

I have created basic schema with timestamps, but when I insert into table in seeder, column created_at and updated_at are null, but based on the Knex.js documentation I thought it should be current datetime if not specified.
Latest adonis libraries, database: mysql 5.7.
My Schema
'use strict'
const Schema = use('Schema')
class UserSchema extends Schema {
up () {
this.create('users', (table) => {
table.increments()
table.string('name')
table.timestamps()
})
}
down () {
this.drop('users')
}
}
module.exports = UserSchema
My Seeder
'use strict'
const Factory = use('Factory')
const Database = use('Database')
class UserSeeder {
async run () {
await Database.table('users').insert({
name: 'JP',
})
}
}
module.exports = UserSeeder
Timestamps only works on LUCID ORM. You are using direct database.
Set your json in the fields, it will work:
await Database.table('users').insert({
name: 'JP',
created_at,: Database.fn.now(),
updated_at : Database.fn.now()
})
I have found that timestamps are default only when using models, but not when using database directly. This one is now covered in the documentation. Would be great if it was default on database level instead.
You should add the timestamps arguments like useTimestampType and makeDefaultNow:
table.timestamps(true, true)

.pluck function in strongloop loopback?

Does storongloop loopback has pluck function for a given model ?
For a Product model,
in Rails I can write
Product.where(some_condition).pluck(:name)
It will return an array of names of products matching the condition.
Is there anything similar in loopback?
PS: I know I can use fields filter and then use underscore( or lodash)'s pluck but that's a two step process.
Select specific columns:
{"fields":{"name":true, "email":true}}
Where condition:
{"where":{"id":2}}
Combining:
{"fields":{"id":true},"where":{"id":{"inq":[10,20,30]}}}
The above code works in swagger. Node.js code would be as follows:
var m = server.models.customer;
m.findOne({
fields: ['name', 'email'],
where: {
id:{inq:[10,20,30]}}
}
}, function (err, data) {
console.log(data);
})