I am getting different ID value in JSON response when checking variable as id & _id in DTO
CASE I ( using id as variable )
DTO for the response
export class UserDetail {
#Expose( )
id: string; //HERE ID is used which gives original id as in db
#Expose( )
name: string;
#IsOptional( )
#Expose( )
mobile: string;
}
Response for this is:
{
"id": "6229df5cc32d3aaef32525e0", // Correct id as in db
"name": "Name1 Title1",
"mobile": "AB391C339",
},
{
"id": "6229df7bc32d3aaef32525e3", // Correct id as in db
"name": "Name2 Title2",
"mobile": "CDE393F339",
}
CASE II ( using _id as variable )
Now changing DTO
export class UserDetail {
#Expose( )
_id: string; //HERE _id is used which gives different id value from original one and subsequent ids are in incremental fashion
#Expose( )
name: string;
#IsOptional( )
#Expose( )
mobile: string;
}
Response for this is:
{
"_id": "624023c8193f2404f8312ccb", // Not same as present in db
"name": "Name1 Title1",
"mobile": "AB391C339"
},
{
"_id": "624023c8193f2404f8312ccc", // Not same as present in db
"name": "Name2 Title2",
"mobile": "CDE393F339"
},
Schema for user is:
#Schema( )
export class User extends Document {
#Prop( { required: true } )
name: string;
#Prop( { required: true } )
mobile: string;
}
Another Observation: With the use of _id in dto, all the ids in response are in incremental fashion. eg. cb, cc, cd, ce
& with only id in dto it's showing ids as original id in db.
Library & Framework Used: NestJs, Fastify, Mongoose, Class-Transformer
i don't quite understand your question...
you need to give some information about what libraries you are using and what you are actually trying to do.
so far i can only tell you that mongodb uses the _id filed as a unique identifier for each record.
the value for this identifier also relies on the time at which it is created (read more)
some libraries also add a virtual field id to each entry which links back to _id, this is only done for cosmetic purposes.
each table entry needs such a unique id for indexing and relational data modeling.
i hope this provided at least something useful to you
According to what you wrote only explanation that came to my mind is that your documents accually contain both fields id and _id, that might happen if someone imported documents directly to database in some wired way. It happened to me once when I imported raw json backup.
As far as I can see from the code you shared, there is no such thing as "id" in you schema.
Look at this post and see if it helps you figure it out.
Related
I am using NestJS to build an api, and everything is working great so far!
I have a users table and a corresponding users.entity.ts file:
#Entity({ name: 'users' })
export class User extends BaseEntity {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column({
unique: true,
})
email: string;
...
I am using AWS Cognito as an authentication provider - everything is working great there too. I am trying not to duplicate things, so I'd like to keep given_name and family_name values with Cognito and not have redundant fields on my postgres table.
I can get the user without problems, but I'm not sure how to "combine" them into my user entity.
For example,
// users.service.ts
const user = await this.usersRepository.findOne({
where: {
id: userId,
},
});
// id: dbc92...
// email: example#email.com
const cognitoUser = await this.cognitoService.adminGetUser(user.id);
// id: dbc92...
// email: example#email.com
// given_name: "Tony"
// family_name: "Stark"
return user;
I don't have a given_name property on my user entity—I'm not sure if I need one?
Ideally, I think what I'm trying to do is something like,
user.givenName = cognitoUser.given_name
user.familyName = cognitoUser.family_name
...
return user
But since my user.entity file doesn't have a givenName property, it's not to happy to do that.
I know I can "merge" the two objects using a spread operator, but I'd like to return the actual user entity if possible. How can I pull from two sources and return the proper entity?
As Mohammad said, if what you are trying to accomplish is:
user.givenName = cognitoUser.given_name
user.familyName = cognitoUser.family_name
then you can do this:
#Entity({ name: 'users' })
export class User extends BaseEntity {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column({
unique: true,
})
email: string;
given_name: string;
family_name: string;
}
and be able to handle the data just from User but without replicating data in the database with unnecessary columns.
You can add your desired properties without adding #Column decorator. It will not make column in your table but still you have them in your entity.
From the official docs: https://github.com/typeorm/typeorm/blob/master/docs/listeners-and-subscribers.md#afterload
You can define a method with any name in entity and mark it with #AfterLoad and TypeORM will call it each time the entity is loaded using QueryBuilder or repository/manager find methods.
TypeORM Entity with custom properties / virtual fields:
// tested with `typeorm#0.3.7`
#Entity()
export class Post {
#AfterLoad()
updateCounters() {
if (this.likesCount === undefined) this.likesCount = 0
}
}
I don't think the chosen answer is quite correct because an exception for missing columns is thrown when an insert or update operation is attempted:
https://github.com/typeorm/typeorm/blob/cdabaa30287d357c0ae994209e573f97f92dad22/src/metadata/EntityMetadata.ts#L806-L814
If you are interested in reading more about the issue, is sounds like a feature selectAndMap is soon coming to typeorm to support this in a way that is more intuitive https://github.com/typeorm/typeorm/issues/1822#issuecomment-376069476
I am facing an issue when trying to update multiply records in once.
I am using method save of Repository of entity.
This is how it is used as written in the docs :
save - Saves a given entity or array of entities. If the entity already exists in the database, then it's updated. If the entity does not exist in the database yet, it's inserted. It saves all given entities in a single transaction (in the case of entity manager is not transactional). Also supports partial updating since all undefined properties are skipped. In order to make a value NULL, you must manually set the property to equal null.
await manager.save(user);
await manager.save([
category1,
category2,
category3
]);
This is how I am using it :
#Injectable()
export class PersonService{
constructor(
#InjectRepository(PersonEntity)
private personService: Repository<PersonEntity>,
) {}
async saveAll(persons: PersonEntity[]) {
return await this.personService.save(persons);
}
}
The persons input param contains only keys attr and wanted attr to update.
And I am getting this error:
[ExceptionsHandler] null value in column "*****" violates not-null constraint +17149ms
QueryFailedError: null value in column "****" violates not-null constraint
Thank you for you help!
The save() method check if columns with PrimaryColumn() decorator contains values to determine whether to update or insert the record.
For example:
#Entity({ name: 'persons'})
export class Person {
#PrimaryColumn()
id: number
#Column()
name: string
#Column()
age: number
}
Now assuming you passed the following person entity to save()
[
{
"id": 1,
"name": "John",
"age": 7
},
{
"id": null,
"name": "Bob",
"age": 8
}
]
John will be updated, while Bob will be inserted.
In your case, I am suspecting that you do not provide value to your primary column so theTypeORM trying to insert the record into db and that record contains null value for the non-null column.
I have a JSON I would like to put into my mongo db database. My JSON holds some relational data. This data is internal to that JSON, I don't need to store this anywhere else. Example:
{
title: "John film list"
films [
{
title: "Once upon a time in Hollywood"
director: '1a' //referencing the director using an ID of type string
},
{
title: "Some film with empty director field",
director: ''
}
],
directors: [
{
id: '1a', //find the director here
name: 'Tarantino'
}
]
}
I do not need to store anything centrally (I don't need a big list of directors somewhere), but in this very document I need to be able to look up the director (1a) and get back Tarantino.
I managed to push this JSON format to MongoDB. However, it gives my schemas new ids (_id-field) and I am confused now as to how to relate the two properly in mongo?
The default unique primary key in the MongoDB document is _id. When you insert a new document, it returns the unique id of the record that inserted (created).
The value inside this id is ObjectId who creates based on time. you can read about it here.
If you want to use your own value for the _id, have to pass it when you call the insert, like this:
db.directors.insertOne({_id: '1a', name: 'Tarantino'})
I'm working with NodeJS and MongoDB,
Actually I'm have a doubt about the datastructure that I'm using in MongoDB, currently I save my data in the database like this:
{
"_id" : ObjectId("4f9519d6684c8b1c9e72e367"),
"tipo" : "First Post on MongoDB",
"rates": {
"user": "5c981a0f8a76d426dc04619e",
"votation": 1
},
}
But the way that I want to store the data is in this structure:
{
"_id" : ObjectId("4f9519d6684c8b1c9e72e367"),
"tipo" : "First Post on MongoDB",
"rates": {
"5c981a0f8a76d426dc04619e":{
"votation": 1
}
},
}
I had been trying to save the data like in the last example, but I don't achieve it,
Here is the way as I have my const in NodeJS.
const post = {
tipo: body.tipo,
user: body.usuario,
duration: 25,
rates:
{
user: body.usuario,
votation: 1
}
};
And Here is how I have my model:
interface IPost extends Document {
tipo: String;
user: Object;
duration: number;
rates: Object;
}
Can someone explain me how can I do it please?
Regards.
If you need to store key/value properties related to the main document and then just visualize them, probably you need mongoose maps.
A map's keys are always strings.
rates: { type: Map, of: Number }
In this way you can have something like this:
rates: {"5c981a0f8a76d426dc04619e": 1}
Using this schema you can have multiple rates, one for each user/key.
But, as noted in the comments, this could be a sub optimal solution if need to do queries against these keys/values. In this case, an external schema reference should be used. In this case I'd use a three schema approach: Post, User and Rates.
a Post has multiple rates
a Rate belongs to the User and Post couple
I found a similar question already asked on SO.
Okay, so I'm starting to dig into graphql a little bit, and I've built an api using koa, type-graphql, and sequelize-typescript. Everything works pretty well.... I managed to get a query working, and even managed to optimize a little bit by using graphql-fields to filter the columns I query in the database... However when I've aliased a field name, I can't seem to get the mapped name.....
For example, given the following ObjectType/Sequelize Model....
export interface IDepartment {
departmentId: number;
name: string;
description: string;
}
#ObjectType()
#Table({ underscored: true })
export class Department extends Model<Department> implements IDepartment {
#Field({ name: 'id' })
#PrimaryKey
#Column({ field: 'department_id'})
public departmentId: number;
#Field()
#Length({ max: 100 })
#Column
name: string;
#Field()
#Length({ max: 100 })
#AllowNull
#Column
description: string;
}
and sample query....
query {
department(name: "Test Dept") {
id
name,
description
}
}
sample resolver...
async department(#Arg('name') name: string, #Info() info: GraphQLResolveInfo) {
return Department.findOne({
where: { name }
});
}
This works just fine.... but when I do
async department(#Arg('name') name: string, #Info() info: GraphQLResolveInfo) {
let fields = Object.keys(getFields(info))
return Department.findOne({
attributes: fields,
where: { name }
});
}
(getFields is graphql-fields), it fails because the query specified field name id, which is what graphql-fields returns, but the column name is department_id (sequelize model name departmentId).
I've gone through the schema with a fine tooth comb, using the introspectionFromSchema function to see a detailed copy of my schema, but nowhere is there a mention of departmentId or department_id.... However I know it's out there somewhere because when I exclude the attributes field from my sequelize query, even though sequelize returns departmentId as the property name, when I return it from my resolver and it reaches the client, the property name is id.
Any help would be appreciated.... I'm trying to optimize everything by only fetching requested properties and not the entire object. I could always store the maps as separate constants and use those in my #Field definition, but I want to do that as a last resort, however if I can I'm trying to keep the code as lean as possible....
Thank you all in advance.
Unfortunately, the name option was introduced mostly to support resolvers inheritance. Using this for mapping the schema field names is a kinda undocumented feature so it's doesn't provide any mapping or exposing mapping metadata.
Using the name option for input or args types will be even worse - it will result in no access to the fields and the properties being undefined.
For now my recommendation is to just keep it simple and don't map the field names until a proper fix arrives.