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){ ...
Related
I'm trying to have each record attached to a user who created it,
and every user have their records attached.
Here are my schemas:
1.The Records schema:
const mongoose = require('mongoose')
const RecordsSchema = new mongoose.Schema(
{
Title: { type: String, required: true },
postedby:[{
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
}],
Author: { type: String, required: true},
ISBN: { type: String, required: true },
Review: { type: String },
SelectedFile: { type: String },
Likes: { type: Number, default:0},
Date: { type: Date, default: Date.now()}
});
module.exports = Records = mongoose.model('record', RecordsSchema', 'record');`
Here is the The user Schema:
const mongoose = require('mongoose')
const userSchema = new mongoose.Schema(
{
username: { type: String},
email: { type: String, required: true ,unique:true},
records:[{
type: [mongoose.Schema.Types.ObjectId],
ref: 'record' }],
password: { type: String, required: true},
Date: { type: Date, default: Date.now(), immutable: true }
});
module.exports = User = mongoose.model('user', userSchema,'user');
The express route for getting a record:
router.get('/postedby/', (req, res) => {
Records.find(req.params.id)
.populate('postedby')
.exec()
.then(post =>{
if (!post) {
return res.status(400).json({ msg: 'Add Posts' });
}
else return res.json(post);
}).catch (err => console.error(err))
});
Result of the route:
{
"postedby": [],
"Likes": 0,
"_id": "5fed8c12a4fb2c1e98ef09f6",
"Title": "New Age",
"Author": "Situma Prisco",
"ISBN": "23422",
"SelectedFile": "",
"Review": "",
"Date": "2020-12-31T08:30:10.321Z",
"__v": 0
},
I'm getting a blank Array on the populated user field(posteddby) .
Please help, What am I doing wrong? And yes, i do have a User Logged in
You are too close.
In your schema definition, postedby field itself is an array. Hence you can simply define it like :
postedby:[{
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
}]
Make sure that the ObjectID is stored properly in the postedby array.
Also, you are trying to find a single record based on the ID, hence you can use findById(req.params.id) or findOne({_id:req.params.id}) which would return a single document.
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 am new in MongoDB/Mongoose and have the following problem:
my schema is nested with:
profile: {
school: {type: String, required: false},
subject: {type: String, required: false},
graduation: {type: String, required: false}
}
now i want to update school, subject and graduation with:
userRouter.put('/:id', function(req, res, next){
var updateObject = req.body;
User.findByIdAndUpdate(req.params['id'], updateObject,{upsert: true}, (err, success)=> {
if(err)
res.status(404).send(err);
res.status(200).send();
});
});
i know the put method replace the object, but the patch method doesn't run in my code. Now, when i sent:
{"school": "", "subject": "c", "graduation": ""}
subject and graduation will be overwritten, but school will not be empty - it contains the old stuff.
Do you have a solution? Thanks.
Tested like this school and graduation were modified...
let updateObject = {
profile: {school: "", subject: "c", graduation: ""}
};
user.findByIdAndUpdate(
req.params['id'],
updateObject,
{upsert: true},
function(err, success) {
if (err)
res.status(404).send(err);
res.status(200).send();
}
);
Used this testing schema:
new mongoose.Schema({
created: {type: Date, required: true, default: Date.now},
modified: {type: Date, required: true, default: Date.now},
profile: {
school: {type: String, required: false},
subject: {type: String, required: false},
graduation: {type: String, required: false}
}
},
{
collection: 'db_test',
strict: 'throw',
toJSON: {getters: true},
toObject: {getters: true}
}
);
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);
});
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.