How to add a unique constraints through Loopback 4 Model? - loopbackjs

I have a Department model in my project. The properties are id, name. name of course should be unique. However I can't seem to look where the setting is so I can put something like
#model()
export class Department extends Entity {
#property({
type: 'number',
id: true,
generated: true,
})
id?: number;
#property({
type: 'string',
required: true,
unique: true // ---> This is what I want. But how?
})
name: string;
constructor(data?: Partial<Department>) {
super(data);
}
}
I tried digging to Model documentation, it seems that there is something I can do with the #model decorator. However I found no documentation about it.
Also, I want to do this in PostgreSQL as a datasource. Any clue? Any advice would be appreciated.

#property({
type: 'string',
required: true,
index: {
unique: true,
}
})
name: string;
Using index object.
Migrate Database - Modify or alter table
run command : npm run build
migrate database : npm run migrate

Related

Can I have camel case as default when using postgres in loopback?

If you don't specify anything all the fields are created as lower case in the database when using postgres. Is it possible to change the default behavior to use the exact name of the fields in the model? That makes it easier to write custom queries.
As it is now I have to configure the property on each field to say that they should be camel case, and that is quite error prone since that is something that is easy to forget.
If that isn't possible, is it possible to use the functionality in the repository that does the mapping from all lowercase to the fields in the models in an easy manner somehow?
Not sure if this helps, but you can use name property
example:
export class User extends .... { #property({
type: 'number',
id: true, }) id?: number;
#property({
type: 'string',
required: true,
name: 'first_name',
})
firstName: string;
#property({
type: 'string',
name: 'last_name',
})
lastName: string;

Loopback 4: non-primitive properties instead of relations

Using Loopback 4, I want to use the type-safety of Typescript in my application code while getting the schema validation from the repository decorators, but store a property as serialized json (in this case, Postgres bson) instead of as a separate entity with a FK relation.
Consider a address book Contact model that could have a list of phone numbers:
#model()
export class PhoneNumber {
#property({ required: true })
number: string;
#property()
type: string;
}
#model()
export class Contact extends Entity {
#property({ id: true, required: true })
id: string;
#property({ required: true })
email: string;
#property({ required: true })
name: string;
#property.array(PhoneNumber)
phoneNumbers: PhoneNumber[];
constructor(data?: Partial<Contact>) {
super(data);
}
}
In the above example, I get full schema validation, but if I try to save an instance of Contact using a generated Repository that extends DefaultCrudRespository, it just drops whatever was provided in the phoneNumbers field and saves an empty column in the db.
If I change the property annotation to:
#property.array(Object)
phoneNumbers: PhoneNumber[];
It will save the field properly, serialized as json, but it won't attempt to validate the field, and also won't specify the type as an array PhoneNumber in the generated openapi.json spec
It seems that Loopback 3 had support for embedded models: https://loopback.io/doc/en/lb3/Embedded-models-and-relations.html
No mention of it in the Loopback 4 docs, though.
Try use the strict mode filter in the model PhoneNumber
#model({settings: {strict: "filter"}})
This make any unknow field be ignored when add in the database

DynamoDB AppSync field resolvers timing out

So I have the schema below. If I try to query data off this schema AppSync will time out saying 'NetworkError when attempting to fetch resource.'
type Model {
PartitionKey: ID!
SortKey: ID!
Name: String
Version: Int
FBX: String
# ms since epoch
CreatedAt: AWSTimestamp
Description: String
Tags: [Tag]
}
type ImageSet {
PartitionKey: ID!
SortKey: ID!
Name: String
CreatedAt: AWSTimestamp
Description: String
Tags: [String]
}
Now, if I change 'Name' in the model to 'ModelName' then queries on that will work. If I change 'Name' in ImageSet to 'SetName' then queries on that will work.
What is going on with this? What is wrong with the 'Name' field name? 'Description' and 'CreatedAt' do not have this issue.
Edit
Actually I am encountering this happening with other fields in the
schema as well. Please help.
I do have resolvers attached to specific fields. Removing them does
solve the problem. Am I not supposed to attach revolvers to specific
fields or is something else wrong?
-
Edit 2
This really does seem to only occur if the name of a field is shared
between different schema objects, is that not allowed!?

Ember-data Serialize/Deserialize embedded records on 3rd level

Pardon me for coming up with this title but I really don't know how to ask this so I'll just explain.
Model: Group (has) User (has) Post
Defined as:
// models/group.js
name: DS.attr('string'),
// models/user.js
name: DS.attr('string'),
group: DS.belongsTo('group')
// models/post.js
name: DS.attr('string'),
user: DS.belongsTo('user'),
When I request /posts, my server returns this embedded record:
{
"posts": [
{
"id": 1,
"name": "Whitey",
"user": {
"id": 1,
"name": "User 1",
"group": 2
}
}
]
}
Notice that the group didn't have the group record but an id instead.
With my serializers:
// serializers/user.js
export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
group: {embedded: 'always'}
}
});
// serializers/post.js
export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
user: {embedded: 'always'}
}
});
This expects that the User and Post model have embedded records in them. However, it entails a problem since in the json response doesn't have an embedded group record.
The question is, is there a way I can disable embedding records in the 3rd level?
Please help.
Here is a good article about serialization:
http://www.toptal.com/emberjs/a-thorough-guide-to-ember-data#embeddedRecordsMixin
Ember docs:
http://emberjs.com/api/data/classes/DS.EmbeddedRecordsMixin.html
Basically, what it says is that you have 2 options 1) serialize and 2) deserialize. Those two have 3 options:
'no' - don't include any data,
'id' or 'ids' - include id(s),
'records' - include data.
When you write {embedded: 'always'} this is shorthand for: {serialize: 'records', deserialize: 'records'}.
If you don't want the relationship sent at all write: {serialize: false}.
The Ember defaults for EmbeddedRecordsMixin are as follows:
BelongsTo: {serialize:'id', deserialize:'id'}
HasMany: {serialize:false, deserialize:'ids'}

Get belongsTo ID without fetching record

I'm trying to fetch the belongsTo ID without fetching the actual record. My JSON API returns the ID for the belongsTo relation.
I have the following models
App.Recipe = DS.Model.extend(
title: DS.attr()
ingredients: DS.hasMany('ingredient', async: true)
)
App.Ingredient = DS.Model.extend(
recipe: DS.belongsTo('recipe')
product: DS.belongsTo('product', async: true)
)
App.Product = DS.Model.extend(
title: DS.attr()
)
This is my route:
App.RecipeIndexRoute = Ember.Route.extend(
model: (args) ->
#store.find('recipe', args.recipe_id)
)
This is my controller:
I'm trying to find the product id within this controller.
App.RecipeIndexController = Ember.ObjectController.extend(
hasRecipeInCart: null
actions:
toggleCart: ->
#content.get('ingredients').then((ingredients) =>
# how do I get product id here, without lookup up the product relation?
# this 'get' makes Ember call: /api/v1/products/1
# I simply want the product ID (in this case 1), without having to call the server again.
ingredient.get('product').then((product) =>
product.id # => 1
)
My JSON looks like this:
HTTP GET: /api/v1/recipes/1
{
"recipe": {
"id":1,
"title":"Recipe 1",
"ingredients":[2,1]
}
}
HTTP GET: /api/v1/ingredients?ids[]=2&ids[]=1
{
"ingredients": [
{
"id":2,
"recipe":1,
"product":1
},
{
"id":1,
"recipe":1,
"product":2
}
]
}
This is now much easier with the ds-reference feature that was added to ember data. You can now do:
var authorId = post.belongsTo("author").id();
See http://emberjs.com/blog/2016/05/03/ember-data-2-5-released.html#toc_code-ds-references-code
A ton of work is going into redoing the relationships, you can pull it out of the underlying properties from the data attribute model.get('data.product.id')
Example: http://emberjs.jsbin.com/OxIDiVU/16/edit
For ED 2.x, relationships have been reworked and were broken for getting underlying data until the ds-references feature landed.
To do this in ED 2.4+, you need to use the new belongsTo method to work with underlying data.
To get an id for a belongsTo ref:
var id = this.get('model').belongsTo('myBelongsToKey').value();