Waterline: Create or update a populate record - sails.js

My question is basic but I can not find an answer in the documentation. I have two models: 'Person' and 'Location' being associated One-to-one. I want to create or update 'populated child records' in the Location collection.
let person = await Person.findOne({ phone: inputs.phone }).populate('reside');
Well return
{ reside: [],
createdAt: 1540081110195,
updatedAt: 1540331824622,
id: '5bcbc5d609618e2cfbe64883',
phone: '+42424242',}
I want to create new location record (when they do not exist) or update if their exist. I try
let location = await Location.update({ id: person.reside.id })
.set({city: inputs.city,
street: inputs.street,
}).fetch;
But it does not work when no record has been created yet.
model/Person.js
phone: {
type: 'string',
unique: true,
},
reside: {
collection:'location',
via: 'owner'
},
models/Location.js
city: { type: 'string' },
street: { type: 'string' },
owner:{
model:'person',
unique: true
}
I use action2

I finally found here methods .addToCollection(), .removeFromCollection(), or .replaceCollection() to modify the populated values of a particular record or set of records. It does not seem to be the most appropriate place in the doc to talk about it

Related

Find one and insert into child referenced document

I have a User model, with a referenced child array of objects, I would like to find the User, and insert into the child referenced document, I don't want to update the child document, but rather insert another object into the reports document array.
Below is the User model, I basically want to find the User, and insert into Reports.
const User = mongoose.model(
"User",
new mongoose.Schema({
firstName: String,
lastName: String,
dateOfBirth: String,
email: String,
password: String,
agreedToTerms: Boolean,
agreementDate: String,
verified: Boolean,
roles: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Role"
}
],
reports: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Reports"
}
]
})
);
Thank you!
You can use findByIdAndUpdate with $push:
User.findByIdAndUpdate(<user-id>, {
$push: { reports: <report-id> }
});

How to navigate through documents in a circuler linked list fashion in MongoDB?

I have a really simple User model.
const userSchema = mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
address: {
type: String,
default: null,
},
description: {
type: String,
default: null,
},
active: {
type: Boolean,
default: true,
},
interests: [
{
type: String,
default: null,
},
],
favorites: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
default: null,
},
],
});
I have a use-case where the client should be able to navigate through the users one by one in a circular fashion. I was able to implement the functionality for getting the next and previous user relative to a specific user through the
this answer.
However, the issue with this is that if I try to get the previous document on the first document in the Users collection, it of course returns an empty object. And same is the case when I try to get the next document on the last document.
I want to tweak it so that if I try to get the previous document on the first document, it would return me the last document, and if I try to get the next document on the last document, it would return me the first document. Just like how you traverse through a circular linked list. Any help would be appreciated! Thanks.

SailsJs: how to use find for array of object attribute?

i have a model that it has some json type attribute and now I want to use find on this json attribute. may please help how can i do it?
model:
module.exports = {
attributes: {
ownerInfo: {
type: 'json',
description: 'owner info of Task',
example: {id: '', fullName: '', emailAddress: ''}
},
name: {
type: 'string',
required: true,
description: 'Name of Task',
example: 'Business App'
},
users: {
type: 'json',
columnType: 'array',
description: 'Users id of task',
defaultsTo: [],
example: [{id :'', emailAddress: '', fullName: '', status: ['admin', 'leader', 'user']}]
}
}
}
actually i need 2 different query, one for finding ownerInfo.id and another else is finding user[].id.
in second query attribute is Array.
I searched a lot in Internet and tried many time with the queries like below but have not got any result.
tasks = await Task.find({
where: {
ownerInfo: {
id: params.id
}
}
})
for Array i had no any Idea how to search in Array of Object. please share your Idea.
tasks = await Task.find({
where: {
users: {
// how to search status of user ??
}
}
})
and also in MongoDb better I save short user info in task collection or like relative DB only keep the id of them and with populate reach that data? which method is faster and better as performance?
advanced thanks

Mongoose: reference between models with same schema keys

As a front-end developer, I would like to have some isomorphic object for two mongoose models.
Let's say I have a user profile:
const profileSchema = new Schema({
firstName: { type: String },
lastName: { type: String },
// example of difference between model schemas
__user: { type: ObjectId, ref: 'Users' },
}
And I would like to create a list of Contact, where each contact will have some of the same keys:
const contactSchema = new Schema({
firstName: { type: String },
lastName: { type: String },
__profile: {
type: ObjectId,
ref: 'Profiles',
unique: true,
},
comment: { type: String },
}
NOTE: Contact could be the both:
as a reference to the Profile
and as independent record in DB / document.
==============================
My question: which is the best way to, organize models on such a way, so
contact could be a reference to the profile
when similar Profile key, like firstName will be updated, contact firstName will be updated too
AVOID of next ref
await Contact.findById(SOME_ID).populate('__profile');
// result
{
firstName: '',
lastName: '',
__profile: {
firstName: 'Chuck',
lastName: 'Norris',
}
}
Desired result - keep contact "isomorphic" like:
{
firstName: 'Chuck', // the key value from profile
lastName: 'Norris', // the key value from profile
__profile: SOME_PROFILE_ID,
}
Is this possible?
P.S: in my app, I'm using refs and started to use discriminators approaches.
I'd approach this task either:
1) put all data inside 1 collection (e.g. Profile):
// Profile model
{
firstName: 'Chuck',
lastName: 'Norris',
contacts: [{
type: ObjectId,
ref: 'Profile',
unique: true,
}],
...all other properties
}
that way you will be able to store just contacts (e.g. when I want to add just a contact) and profiles with much more info.
2) or will use discriminators to create a base class (e.g. Contact) and build Profile model upon it:
const options = { discriminatorKey: 'userType' };
const Contact = mongoose.model('Contact', new mongoose.Schema({
firstName: String,
lastName: String
},
options)
)
const Profile = Contact.discriminator(
'Profile',
new mongoose.Schema(
{
contacts: [{
type: ObjectId,
ref: 'Contact',
unique: true,
}],
comments: []
},
options
)
);
that way you will be able to save Contacts and Profiles inside 1 collection and reference base class (Contact) for contacts inside Profile
Hope that helps!
In my case, complete usage of Mongoose discriminators did not give me an advantage, because discriminators give you an opportunity to:
They enable you to have multiple models with overlapping schemas on
top of the same underlying MongoDB collection.
As a result, by using discriminators approach, I will reive one collection
of:
profiles
And there will be a mix of users and contact profiles.
==============================
So I decided to use two approaches:
create BesaSchema for the profile
take advantage of Mongoose Subdocuments
RESULT:
// keys which are same for both user Profile and Contact
const Schema = require('mongoose').Schema;
const util = require('util');
function BaseProfileSchema(...args) {
Schema.apply(this, args);
this.add({
firstName: { type: String },
lastName: { type: String },
});
}
util.inherits(BaseProfileSchema, Schema);
// user Profile Model
const profileSchema = new BaseProfileSchema({
__user: {
type: String,
ref: 'users',
required: true,
unique: true,
},
});
const Profile = mongoose.model('profiles', profileSchema);
// Contact with profile as subdocument
const contactProfileSchema = new BaseProfileSchema();
const contactSchema = new Schema({
// Associations
__refProfile: {
type: Schema.Types.ObjectId,
ref: 'profiles',
index: {
unique: true,
sparse: true,
},
},
profile: contactProfileSchema,
});
const Contact = mongoose.model('contacts', contactSchema);
As a result, I'm having DB with next collections:
users
profiles
contacts
Both profiles and contacts.profile are IDENTICAL because I'm extending the base shared schema.
Moreover:
inside Contact I'm having different keys for real referenced profile (__refProfile which can NOT be edit by others) and contact.profile
profile inside connection can be edited ONLY when the contact was edited by itself
P.S: happy codding 👨‍💻🍻

Sails js One-to-Many Relationship with custom column names

Faced serious problems here with Sails Js.
So, i have one-to-many relationship as described below (taken from official sails documentation):
// myApp/api/models/User.js
// A user may have many pets
module.exports = {
attributes: {
firstName: {
type: 'string',
columnName: "first_name"
},
lastName: {
type: 'string',
columnName: "last_name"
},
// Add a reference to Pets
pets: {
collection: 'pet',
via: 'owner'
}
}
};
and dependent model:
// myApp/api/models/Pet.js
// A pet may only belong to a single user
module.exports = {
attributes: {
breed: {
type: 'string'
//column name will be 'breed' by default
},
typeProperty: {
type: 'string',
columnName: "type_property"
},
nameProperty: {
type: 'string',
columnName: "name_property"
},
// Add a reference to User
owner: {
model: 'user'
}
}
};
When I'm calling in the code following query
User.find()
.populate('pets')
.exec(function(err, users) {
if(err) // handle error
// The users object would look something like the following
[{
id: 123,
firstName: 'Foo',
lastName: 'Bar',
pets: [{
id: 1,
// !! Only this property is loaded !!
breed: 'labrador',
// !! This property is NOT loaded !!
typeProperty: undefined,
// !! This property is NOT loaded !!
nameProperty: undefined,
user: 123
}]
}]
});
Basically, seems that sails (waterline if to be specific) is not mapping back properties, which have custom "columName" specified and differs from property name (ex. "typeProperty" stored in type_property column).
Has anyone faced this kind of problem?
In fact, I faced this problema. The property "columnName" is not working. Seems like Sails doesn't prioritizes this property over it's model's convention naming.
Try to change the model attribute name to be equal your database property.
type_property: {
type: 'string'
},
this should make your attributes to be populated. Worked here.
Column name works fine when the attribute in question is a foreign key.