I have following schemas in the app
var UserSchema = mongoose.Schema({
email: {type: String, index: {unique: true, sparse: true}},
password: String,
createdOn: {type: Date, default:Date.now },
purchaseDate:Date,
expiryDate:Date,
purchaseID: {type: String, index: {unique: true, sparse: true}},
isEnabled: {type: Boolean,default: true},
devices:[{
type:mongoose.Schema.Types.ObjectId,
ref: 'Device'
}]
});
var DeviceSchema = mongoose.Schema({
owner : { type:mongoose.Schema.Types.ObjectId, ref: 'User' },
uuid:String,
token: String,
createdOn: {type: Date, default:Date.now },
lastSeen: Date,
isEnabled: {type: Boolean, default:true }
});
Let's say I have following users
User 1
{
"_id": ObjectId("56ec014111cb350404e30005"),
"purchaseDate": new Date("2015-10-17T17:01:26+0300"),
"purchaseID": "570000118683786",
"devices": [
ObjectId("56ec016911cb350404e30006")
],
"isEnabled": true,
"createdOn": new Date(1458307393521),
"__v": 1
}
User 2
{
"_id": ObjectId("57ec014111cb350404e30005"),
"devices": [
ObjectId("57ec016911cb350404e30006")
],
"isEnabled": true,
"createdOn": new Date(1458507393521),
"__v": 1
}
What is the proper way to merge devices array of User 2 to User 1 and get rid of User 2 completely?
You could fetch User1's devices and update User2 (assuming User2 is already fetched) :
UserModel.findById(user1Id)
.then(function (user1) {
// addToSet will ensure no duplicates in user2.devices
user2.devices.addToSet(user1.devices);
});
Related
I'm fairly new to Mongo and Mongoose, so if this question is rather silly then feel free to point me in the right direction.
I have a API with models for users and stories that they published. When I display the users, I want the stories to show as well.
The relation is drawn rather simply:
const userSchema = mongoose.Schema({
username: {
type: String,
unique: true,
},
password: String,
firstName: {
type: String,
required: false,
},
lastName: {
type: String,
required: false,
},
birthday: {
type: Date,
},
bio: {
type: String,
required: false,
},
country: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Country',
},
stories: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Story',
}]
})
With a stories scheme declared as such:
const storySchema = new mongoose.Schema({
name: {
type: String,
max: 255,
},
url: {
type: String,
unique: true,
},
description: {
type: String,
required: false,
},
length: {
type: Number,
default: 0,
},
createdAt: Date,
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
language: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Country'
},
type: {
type: mongoose.Schema.Types.ObjectId,
ref: 'StoryType'
},
genre: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Genre'
},
})
I print the values using the simple find method (the action for now is only meant to show all of them.
app.get('/list-users', async (req, res) => {
const users = await User.find().populate('country').populate('stories').exec();
res.json(users);
});
Unfortunately, although the results show all the values properly, the stories array does not get populated at all.
[
{
"_id": "6127ce5b0576979256fd3e08",
"username": "test",
"password": "123",
"firstName": "tst",
"lastName": "tst",
"birthday": "1995-11-02T00:00:00.000Z",
"country": {
"_id": "6127c020f95eb5abf72f713a",
"name": "Poland",
"languange": "Polish",
"__v": 0
},
"stories": [],
"__v": 0
}
]
The docs have a clear indicator that such schemas will return an empty array, and I am aware I could just run a find by User and populate with that but I'm wondering what is the cleanest solution to apply in a situation like this.
Any help would be of great value.
I want to add the data inside the order products_id array
I tried to push the array by find it by user id and then add push it inside the products_id but i won't able to add the data.
User.findById(user_id,(err,user)=>{
if(err) throw err;
const lastOrderId = user.order.slice(-1)[0]._id
//console.log(cb.order.slice(-1)[0]._id);
User.update({'order[0]._id': lastOrderId}, {$push: {'order.0.$.products_id': 123}},{safe:true,upsert:true})
/*User.findOneAndUpdate({'_id' : user_id, 'order._id': lastOrderId}
,{$push: [{'order[0].products_id': [123123]}]},{safe:true,upsert:true})*/
})
My User Schema
const userSchema = mongoose.Schema({
_id: mongoose.Types.ObjectId,
user_name: {type:String,require: true},
email: {type:String, require: true},
password: {type:String,require:true},
full_name: {type:String},
order: [{
_id: mongoose.Types.ObjectId,
products_id: [],
date: {
type: Date,
default: Date.now
}
}]
})
After updating i want
const userSchema = mongoose.Schema({
_id: mongoose.Types.ObjectId,
user_name: {type:String,require: true},
email: {type:String, require: true},
password: {type:String,require:true},
full_name: {type:String},
order: [{
_id: mongoose.Types.ObjectId,
products_id: [5d5d7a7ea0c4aaf6212993ec, 5d627a962a5c637e7a0d5d1c, 5d627a49fa24ba7d15451afb],
date: {
type: Date,
default: Date.now
}
}]
})
You can use arrayFilter for this.You can do it like this.
User.update({user_id},{$set: { 'order.$[ord]': lastOrderId },
$push: {'order.$[ord].products.$[prd]':123}
}, {
arrayFilters: [{'_id': user_id}]
})
Is it possible to use mongoose's Populate Virtuals to populate the array of values it is referencing?
User Model
var userSchema = new mongoose.Schema({
auth_key: {type: String},
channels: [{
name: {type: String},
last_access: { type: Date, default: Date.now },
status: {type: String, default: false },
new_messages: {type: Number},
user_channel_group: {type: String}
}]
}, {
toJSON: {
virtuals: true
}
});
userSchema.virtual('channels.details', {
ref: 'channel',
localField: 'channels.name',
foreignField: 'name'
});
var user = mongoose.model('user', userSchema, 'user');
Channel Model
var channelSchema = new mongoose.Schema({
name: {type: String, required: true},
members: [{ type: String, required: true }],
displayName: {type: String},
type: {type: Number},
create_at: {type: Date, default: Date.now}
});
var channel = mongoose.model('channel', channelSchema, 'channel');
My query that I am using I want the virtual to present the channel details from each channel alongside the channels a user is subscribed to. so something like this..
[{
"_id": "588a82ff7fe89686fd2210b0",
"channels": [{
"details": {
"_id": "588a80fd7fe89686fd2210a8",
"name": "channel1",
"members": []
},
"name": "channel1"
}, {
"details": {
"_id": "588a80fd7fe89686fd2210a9",
"name": "channel2",
"members": []
},
"name": "channel2"
}],
"id": "588a82ff7fe89686fd2210b0"
}
...
]
My Query for this is ..
user.find({}).populate('channels.details').exec()
I'm trying to create a webapp with mongoose and nodejs. This is the first time i'm using mongoose and nodejs so i'm not quit good at it.
I have a person model:
var PERSON = new mongoose.Schema({
name: {type: String, required: true},
zipcode: {type: String, required: true},
city: {type: String, required: true},
street: {type: String, required: true},
address: {type: Number, required: true},
email: {type: String, required: true},
type: {type: String, enum: ['lid', 'passant'], required: true},
ships: {
type: [{
name: {type: String, required: true},
length: {type: Number, required: true},
type: {type: String, required: true},
picture: {type: Buffer, required: false}
}],
required: false
},
user: {
type: {
userName: {type: String, required: true},
password: {type: String, required: true},
passwordKey: {type: String, required: true},
roles: {type: [{type: mongoose.Schema.Types.ObjectId, ref: 'role'}], required: true}
},
required: false
}
},
{
collection: 'PERSON'
});
And the rol model:
var ROLE = new mongoose.Schema({
name: {type: String, required: true}
},
{
collection: 'ROLE'
});
When i'm trying to run a find query on the person model, I want to populate the user.roles array. But as a result it remains empty.
/ GET a specific person by id or type/
server.get('/api/person/:id', function (req, res, next) {
if (helper.isValidObjectID(req.params.id)) {
person.findById(req.params.id).populate("user.roles").exec(function (err, result) {
if (err) {
res.status(404).json(err);
} else {
res.status(200).json(result);
}
}
);
} else {
next();
}
}, function (req, res, next) {
person.find({type: req.params.id}).populate('user.roles').exec(function (err, result) {
if (err) {
res.status(404).json(err);
} else {
res.status(200).json(result);
}
});
});
and as a result i get:
{
"_id":"553f79d4f1481c0c14b42d59",
"name":"Wilco Boogert",
"zipcode":"4305RH",
"city":"Ouwerkerk",
"street":"baalpapenweg",
"address":2,
"email":"wilcoboogert17#gmail.com",
"type":"lid",
"user":{
"userName":"wboogert",
"password":"sha1$168fd599$1$502b965cb083ebdfcafb17e655455ef63779e1a1",
"passwordkey":"kfjvlksdfm",
"roles":[
]
},
"__v":0,
"ships":[
{
"name":"titanic",
"length":269,
"type":"Olympic-klasse",
"_id":"553f79d4f1481c0c14b42d5a"
}
]
}
The orginal object in the database is:
{
"_id": {
"$oid": "553f79d4f1481c0c14b42d59"
},
"name": "Wilco Boogert",
"zipcode": "4305RH",
"city": "Ouwerkerk",
"street": "baalpapenweg",
"address": 2,
"email": "wilcoboogert17#gmail.com",
"type": "lid",
"user": {
"roles": [
{
"$oid": "5522996f0fff331ed03cae6c"
}
],
"passwordkey": "kfjvlksdfm",
"password": "sha1$168fd599$1$502b965cb083ebdfcafb17e655455ef63779e1a1",
"userName": "wboogert"
},
"ships": [
{
"name": "titanic",
"length": 269,
"type": "Olympic-klasse",
"picture": "<Binary Data>",
"_id": {
"$oid": "553f79d4f1481c0c14b42d5a"
}
}
],
"__v": 0
}
so as you an see the roles is empty. And I search the web but i cannot find what the problem is. Can annyone help me?
You should replace this line :
roles: {type: [{type: mongoose.Schema.Types.ObjectId, ref: 'role'}], required: true}
with this one :
roles: {type: [{type: mongoose.Schema.Types.ObjectId, ref: 'ROLE'}], required: true}
In fact, the reference must be the exact same name as it's defined :
collection: 'ROLE'
It's case sensitive.
I have the below schema structure for my application:
var User = new Schema({
name: {type: String, required: true},
screen_name: {type: String, required: true, index:{unique:true}},
email: {type: String, required: true, unique:true},
created_at: {type: Date, required: true, default: Date}
});
var Line = new Schema({
user: {type: Schema.ObjectId, ref: 'User'},
text: String,
entered_at: {type: Date, required: true, default: Date}
});
var Story = new Schema ({
sid: {type: String, unique: true, required: true},
maxlines: {type: Number, default: 10}, // Max number of lines per user
title: {type: String, default: 'Select here to set a title'},
lines: [Line],
created_at: {type: Date, required: true, default: Date}
});
var Story = db.model('Story', Story);
var User = db.model('User', User);
When i query a Story using the sid i want it to output the lines in that story but also the users screen_name.
Currently i'm using the below to query the story:
app.get('/api/1/story/view/:id', function(req, res){
Story.findOne({ sid: req.params.id }, function(err, story){
if (err) {
res.json(err);
}
else if(story == null) {
res.json(err);
}
else{
res.send(story);
}
});
});
Which just brings back the result like this:
{
"__v": 1,
"_id": "5117878e381d7fd004000002",
"sid": "DIY0Ls5NwR",
"created_at": "2013-02-10T11:42:06.000Z",
"lines": [
{
"user": "511782cab249ff5819000002",
"text": "TESTING",
"_id": "51178795381d7fd004000003",
"entered_at": "2013-02-10T11:42:13.000Z"
}
],
"title": "Select here to set a title",
"maxlines": 10
}
There is a user set-up with that _id but i'm not entirely sure how to output the story and for it to include the users screen_name or even the entire user information along with the output
{
"__v": 0,
"screen_name": "Tam",
"email": "test#test.com",
"name": "Tam",
"_id": "511782cab249ff5819000002",
"created_at": "2013-02-10T11:21:46.000Z"
}
I haven't tested it, but you should be able to use populate to get the full user doc for each lines element like this:
Story.findOne({sid: req.params.id})
.populate('lines.user')
.exec(function(err, story){ ...