I've defined my schema as follow but when I did db.Titles.find() from mongo shell I didn't get all the documents I have listed. What's wrong did I do ? The author is not showing in the mongo shell. I've tried to add some random document in the list still not showing in the mongo ? Once a model is created, can't it be updated or change? This created a problem when I try to access the list in template. Thanks, in advance.
model :
var mongoose = require("mongoose");
var tSchema = new mongoose.Schema({
title: String,
sypnosis: String,
category: Array,
author: {
username: String,
id: { type: mongoose.Schema.Types.ObjectId, ref: "User" }
},
parts: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Part"
}
],
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Comment"
}
]
});
var Title = mongoose.model("Title", tSchema);
module.exports = Title;
Mongo shell query :
db.titles.find().pretty()
{
"_id" : ObjectId("5e0d140e7bf04c6a60f97dbd"),
"category" : [ ],
"parts" : [ ],
"comments" : [ ],
"title" : "New Title",
"sypnosis" : "This si a sypnosis",
"__v" : 0
}
Related
I am using mongoose and I am trying to get users from my mongodb database, Here is what part of my json looks like
"hpCDaKverVWEYukAhAcM8NU6SP73" : {
"admin" : false,
"booksBorrowed" : [ {
"id" : "9780321831552",
"timeStamp" : 1618881802437
}, {
"id" : "9780007204496",
"timeStamp" : 1618881803678
}, {
"id" : "9780316491297",
"timeStamp" : 1618882675513
}, {
"id" : "9780440335160",
"timeStamp" : 1618882676756
}, {
"id" : "9781482287325",
"timeStamp" : 1618887153684
} ],
I am trying to get the books borrowed array
i tried creating a new schema like this
const BorrowedBook = new Schema({
id : {type: String, default: ''},
timeStamp : {type: Number, default: 0},
})
then doing this in mongoose.model
booksBorrowed: [BorrowedBook]
then I do this in server.js
const User = require('./models/user')
app.get('/api/users', function (req, res) {
User.find(function (err, users) {
console.log(users)
})
})
but it just prints this
booksBorrowed: [ [Object], [Object], [Object], [Object], [Object] ],
What am I doing wrong?
You are doing nothing wrong, its just console.log(users) printing this, since it doesnt print nested lvl objects.
You can do console.log(JSON.stringify(users)) or console.dir(users).
I would like to add a photo into a country in mongoose. But country is an array and photo too. Here is my user schema :
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
firstName: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
birthDate: {
type: Date,
required: true
},
sex: {
type: String,
required: true
},
countries: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Country',
photos: [
{
base64: {
type: String,
required: true
},
title: String,
description: String
}
]
}
],
admin: {
type: Number,
required: true
}
});
Here is what I got as data into mongoDB :
The problem is that I only got the id of countries. And I would like to use another field of the document country. Populate works well when I want to get data, but how to populate and then use the fields to update with mongoDB?
Moreover, I don't know how to update data into nested array, I tried :
User.findOneAndUpdate(
{
"name": "CHARLAT",
"countries": "5d2d847b06f2f94118a36518"
},
{ $push : { "countries.photos" : {
base64: "bla"
} }}
)
As you can see, I use a hand written id for country... I could do a find query before on country but can we use populate here?
And I got this in Postman :
Thank you in advance for your help !
If the type is ObjectId, it can't have a photos field, since it's just an _id. It is a reference to another collection.
Updated answer after comments :
The best thing to do IMO is to create a Photo model which would have the file path and the country's _id. The User model would only store a list of Photos [_id].
UserSchema :
{
.....
photos : [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Photo'
}],
.....
}
PhotoSchema :
{
country : {
type: mongoose.Schema.Types.ObjectId,
ref: 'Country'
},
path : String
}
Then, query your Users this way, by populating the photos, and inside each photo, populating the countries :
UserModel
.find(conditions)
.populate({
path: 'photos',
model: 'Photo'
populate: {
path: 'country',
model: 'Country'
}
})
.lean() // Faster and lighter for read-only, simply returns an object
So you should get a User object like this :
{
.....
name : "John",
photos : [{
country : {
name : "Country 1",
code : "C1" // or whatever field you have in your Country model
},
path: "path/to/photo1.jpg"
},
{
country : {
name : "Country 2",
code : "C2"
},
path: "path/to/photo2.jpg"
}]
.....
}
I have a mongoose schema for categories
import mongoose from 'mongoose';
import { imageScheme } from './data.schemas';
mongoose.plugin(require('mongoose-delete'));
mongoose.plugin(require('mongoose-timestamp'));
const Schema = mongoose.Schema;
const catScheme = new Schema({
title: {
type: String
},
subTitle: {
type: String
},
description: {
type: String
},
images: [imageScheme],
icon: {
type: String
},
deleteAt: {
type: Date,
default: null
}
});
const Category = mongoose.model('Category',catScheme);
export default Category;
my image schema is located in another file
const imageScheme = new Schema({
imageCaption : {
type: String
},
imageFileName: {
type: String,
required: true
},
imagePath: {
type: String,
required: true
}
});
and when I am using the model for creating new category its adding the timestamp and deleted for my images array which means its loading the plugins ( mongoose-delete , mongoose-timestamp ) into the sub schema
HOW TO AVOID THAT ?
that is the result
{
"_id" : ObjectId("5d5a822f20179023e008f10c"),
"deleteAt" : null,
"deleted" : false,
"title" : "Eyes and Ears",
"description" : "here you will find all ppe to keep your eye 6 sharp",
"icon" : "glass.svg",
"images" : [
{
"_id" : ObjectId("5d5a822f20179023e008f10e"),
"deleted" : false,
"imageCaption" : "Eyes and Ears",
"imageFileName" : "67acca17-3fc8-416c-bc00-8273770b2115.jpeg",
"imagePath" : "resources/images/67acca17-3fc8-416c-bc00-8273770b2115.jpeg",
"updatedAt" : ISODate("2019-08-19T11:04:15.756Z"),
"createdAt" : ISODate("2019-08-19T11:04:15.756Z")
},
{
"_id" : ObjectId("5d5a822f20179023e008f10d"),
"deleted" : false,
"imageCaption" : "Eyes and Ears",
"imageFileName" : "9f1c5b1f-c1be-48f2-a9bc-8294930fd4c9.jpeg",
"imagePath" : "resources/images/9f1c5b1f-c1be-48f2-a9bc-8294930fd4c9.jpeg",
"updatedAt" : ISODate("2019-08-19T11:04:15.756Z"),
"createdAt" : ISODate("2019-08-19T11:04:15.756Z")
}
],
"updatedAt" : ISODate("2019-08-19T11:04:15.756Z"),
"createdAt" : ISODate("2019-08-19T11:04:15.756Z"),
"__v" : 0
}
It looks like you are plugging the mongoose-delete and mongoose-timestamp in the whole database.
Have you tried the example provided in the plugin pages?
catScheme.plugin(mongoose-timestamp)
catScheme.plugin(mongoose-delete)
After spent 1 day trying to get things done, I think it's time to ask for help.
I want to populate 2 levels of a document.
I tried with populate() but it seems to work only for first level, not deep populate! I read a lot at SO and I know it should work but I think I'm missing something really stupid...
Please let me know where I'm making mistakes.
Here are the relevant code.
Schemas
var compositionSchema = new Schema({
name: {
type: String,
required: true
},
contributions: [{
type: Schema.Types.ObjectId,
ref: 'Contribution'
}]
});
mongoose.model('Composition', compositionSchema);
var contributionSchema = new Schema({
name: {
type: String,
required: true
},
media: {
type: Schema.Types.ObjectId,
ref: 'Media'
}
});
mongoose.model('Contribution', contributionSchema);
var mediaSchema = new Schema({
name: {
type: String,
required: true
}
});
mongoose.model('Media', mediaSchema);
Actual documents saved in MongoDB
compositions:
{
"_id" : ObjectId("59e5db4595fe650a71fb0e07"),
"name" : "Test Pop 7",
"contributions" : [
ObjectId("59e5db4595fe650a71fb0e05")
]
}
contributions:
{
"_id" : ObjectId("59e5db4595fe650a71fb0e05"),
"name" : "Honda",
"media" : ObjectId("59e4ac5dacacd709eac2c856")
}
media:
{
"_id" : ObjectId("59e4ac5dacacd709eac2c856"),
"name" : "Logo_big.png",
"width" : 662,
"height" : 540
}
My tries (= the wrong code?)
In Node JS, when I do this (as per documentation):
Composition.findOne({ name: "Test Pop 7" })
.populate({
path: 'contributions',
model: 'Contribution',
populate: {
path: 'media',
model: 'Media',
}
})
.exec((error, doc) => {
if (error) { console.log(error); }
else {
console.log(doc);
}
});
prints out this, without actually populate the media field:
{ _id: 59e5db4595fe650a71fb0e07,
name: 'Test Pop 7',
contributions:
[ { _id: 59e5db4595fe650a71fb0e05,
name: 'Honda',
media: [Object] } ]
}
It works, keeping in mind the key-word in your question: prints. Printed, with console.log(), it just shows you the type (checked with typeof) of the document included in an array for some (2nd) level of nesting. If you do:
console.log(doc.contributions[0].media[0])
you will see your populated media document.
Let's say I want to look up a user by their _id and check if the "liked" value (array) contains a certain post _id. How do I query the db for this action? Is it okay to just store these _id's in an array or does mongodb convention prefer something else to store as a reference to other documents?
So I just want to check if the user has the post _id in the "liked" array.
var users = new mongoose.Schema({
name : {type: String, unique : true, required : true, dropDups: true},
password : {type: String, required : true}, //hash
liked : [String],
created : {type: Date, default: Date.now}
});
Here is how I think this might look:
function checkIfLiked() {
let uname = "Jim";
let postId = "abc";
//check if $USER has `postId` in $LIKED
user.findOne({$USER: uname},{$LIKED: {$in: postId} }, function(err, results) {
//do something after check
});
}
For the user data
{ "_id" : ObjectId("56effca6e668e15e2eaa6dfe"), "liked" : [ "11", "23", "4" ], "name" : "aa" }
{ "_id" : ObjectId("56effcb1e668e15e2eaa6dff"), "liked" : [ "1", "2", "3" ], "name" : "bb" }
To check the user name aa with 4 in liked array
> db.user.find({liked: '4', name: 'aa'})
{ "_id" : ObjectId("56effca6e668e15e2eaa6dfe"), "liked" : [ "11", "23", "4" ], "name" : "aa" }
but
> db.user.find({liked: '2', name: 'aa'})
No matched result.
Is it okay to just store these _id's in an array or does mongodb convention prefer something else to store as a reference to other documents?
Mongoose population could do that, you can define the user schema as below
var users = new mongoose.Schema({
name : {type: String, unique : true, required : true, dropDups: true},
password : {type: String, required : true}, //hash
liked : [{ type: Schema.Types.ObjectId, ref: 'User' }],
created : {type: Date, default: Date.now}
});
var User = mongoose.model('User', users);