i am new in mongodb database, i want to fetch data from two different collections ( like in mysql use of joins) then how can we do this in mongodb ? Here my collections data
First collection
{
"id": "5b67dbf20b9f9d2830ccaf40",
"title": "Some Text",
"author": "John Doe"
}
Second collection
{
"id": "5b67dbyd48btr9jexya8ehd8",
"pid": "5b67dbf20b9f9d2830ccaf40",
"salary": "50000"
}
Update your NewSchema as:
var NewSchema = mongoose.Schema({
pid: {
type: Mongoose.Schema.ObjectId,
ref: `Firstcollection`
}
});
You can solve it using populate from mongoose.
SecondCollection.find({})
.populate('pid')
.exec(function(err, data) {
console.log(data)
})
Hope it solves your query!!
Related
I am using mongodb 3.6.20, mongoose 5.10.9 and node 14.13.1
The case is the following.
I want to insert a complex object to db. The object contains an array of objects where each object also contains an array of objects. These objects given by a client which sets the ids(O do not have power over the client to change it). I want to remove the ids and let mongo drivers to handle them and generate new ones.
what is given:
let obj = {
property1: {
property2: "str",
property3: 3
},
property4 : [{
_id: "a valid mongo id",
property5: "str",
property6: [{
_id: "another valid mongo id",
property7: "str"
}]
}]
}
what I want to provide to insert query:
let obj = {
property1: {
property2: "str",
property3: 3
},
property4 : [{
property5: "str",
property6: [{
property7: "str"
}]
}]
}
I have tried to remove them recursively but the call stack is exceeded.
Is there any clever way I can achieve that? The option {_id: false} and {id:false} that I found on mongoose documentation are actually only for the returned documents of a query
What about this?
function removeIDs (obj) {
Object.keys(obj).forEach(function (key) {
if (Array.isArray(obj[key])) {
delete obj[key][0]._id;
return removeIDs(obj[key][0]);
}
});
}
removeIDs(obj)
I can't push items into MongoDB array every time that i try to push a new element it creates an empty object and i cant figure out why,
I already used the
Collection.Array.push({element})&
Collection.save()
but i cant figure out a solution
This is My Schema
const Schema = mongoose.Schema;
var ParticipantSchema = new Schema({
nom:{Type:String},
prenom:{Type:String},
email:{Type:String}
})
var CompetitionSchema = new Schema({
nom:String,
date:Date,
place:String,
participant :[ParticipantSchema]
})
module.exports = mongoose.model("Competition",CompetitionSchema);
This is my funtion
exports.addParticipant=function(req,res){
var newParticipant={
"nom":req.body.nom,
"prenom":req.body.prenom,
"email":req.body.email
}
Competition.updateOne(
{ _id:req.body.id},
{ $push: { participant: newParticipant } },
(err,done)=>{
return res.json(done)
}
);
}
the result is always an empty object like below
{
"_id": "5ded0eeb85daa100dc5e57bf",
"nom": "Final",
"date": "2019-01-01T23:00:00.000Z",
"place": "Sousse",
"participant": [
{
"_id": "5ded0eeb85daa100dc5e57c0"
},
{
"_id": "5dee3c1b08474e27ac70672e"
}
],
"__v": 0
}
There is no problem in your code, the only problem is that in schema definition you have Type, but it must be type.
If you update your ParticipantSchema like this, it will work:
var ParticipantSchema = new Schema({
nom: { type: String },
prenom: { type: String },
email: { type: String }
});
You are using another Schema in the Array. This results in so-called subdocuments (https://mongoosejs.com/docs/subdocs.html). Mongoose does not populate subdocuments by default. So all you see is just the _id. You can use the populate method to see all subdocuments in detail. ( https://mongoosejs.com/docs/populate.html ) .
Example :
Competition.
find({}).
populate('participant').
exec(function (err, comps) {
//
});
You can either use populate on the Model or on the Document. For populating a document, take a look at https://mongoosejs.com/docs/api.html#document_Document-populate . There is also a auto-populate plugin available via npm but in most cases it's not necessary : https://www.npmjs.com/package/mongoose-autopopulate .
I want to acess Subdocument using Mongoose
This is my conversations schema :
const Conversations = new mongoose.Schema({
userOneId: {
type: Schema.Types.ObjectId,
ref: 'User'
},
userTwoId: {
type: Schema.Types.ObjectId,
ref: 'User'
}
This is my User Model Schema:
....
conversations: [{ type: Schema.Types.ObjectId, ref: 'Conversations' }]
});
After inserted i get this:
{
"_id": {
"$oid": "5a6fa114ffc53523705d52af"
},
"created_at": {
"$date": "2018-01-29T22:32:52.930Z"
},
"messages": [],
"__v": 0
}
I have inserted this :
"conversations": [
{
"$oid": "5a6fa14a5562572a541bacae"
},
I have put this:
Object.assign(conversation, {userOneId: user._id});
Object.assign(conversation, {userTwoId: friend._id});
I want to acess the "$oid": "5a6fa114ffc53523705d52af" to get the userOneId and userTwoId information.
you need to use populate.
Basically, inside the "conversations" property in a user object, you only have the ObjectId of conversations, not the entire mongoose object. when you're querying the database for a user/users, you have to tell mongoose that you want it to replace the ObjectIds with the entire objects.
//lets say you have a variable, userId, inside of which you have the id
//of a user, and now you're querying the database for that user
User.findById(userId).populate("conversations")
.exec(function(err, foundUser){
if(err){
console.log(err):
} else {
console.log(foundUser.conversations);
}
});
if you were to run the code above with an actual user _id, then (unless you got an error) you would have printed in your console rather than an array of conversation mongoose ids, an array of conversation mongoose objects. the entire things.
if you only wanted the conversations to have two properties, userOneId and userTwoId, then combine populate with select. instead of
.populate("conversations")
use
.populate({
path: "conversations",
select: "userOneId userTwoId"
})
{
"_id": "581dc52e2c26be354164d528",
"name": "vipin",
"__v": 0,
"post": [
{
"like": "today",
"_id": "581dc52e2c26be354164d529",
"comment": [
{
"date": "today",
"username": "vipin",
"_id": "581dc52e2c26be354164d52a",
"detail": [
{
"time": "now",
"day": "saturday",
"_id": "581dc52e2c26be354164d52b"
}
]
}
]
}
]
},
i have a nested subdocument.i want to update comment .date.but i cant do this .i want to nested subdocument update but query is not work.
Test.update({"_id":"581dc52e2c26be354164d528","post._id":"581dc52e2c26be354164d529","comment._id":"581dc52e2c26be354164d52a" },{
"$set":{
"post.$.comment.0.date.0":"tommorow"
}
},function(err,data){
if(data){
res.json(data)
};
if(err){
res.json(err)
}
})
}
my query is now worked .plzz anybody suggest me .
mongodb don't support positional operator matching nested arrays. check this issue it's still in open status:
https://jira.mongodb.org/browse/SERVER-831
workaround : use aggregation and fetch required subdocument make modifications and update subdocument using update query.
Okkk.we can update our nested subdocument in mongodb.this is our schema.
var Post = new mongoose.Schema({
name:String,
post:[{
like:String,
comment:[{
date:String,
username:String,
detail:{
time:String,
day:String
}
}]
}]
})
Now we can update our choosed field in mongoDb.if your document contains more than array of field like post,comment than it can be poor .but we can use many objects.like ......than we have no problem on updating.
post:[{
like:String,
comment:{
date:String,
username:String,
detail:{
time:String,
day:String,
address:{
street:String,
house:String
}
}
}
}]
})
so we have solution of first Schema is like this.our mongoDb query is working properly .so check this...
for first schema.if we have take more than one array in subdocument.
Test.update({"post._id":"58206a6aa7b5b99e32b7eb58"},
{$set:{
"post.$.comment.0.detail.time":"aajtk"}},
for second schema .if we have take more than objects.
db.tests.update({"post._id":ObjectId("58204e89cfee37f023a567bd")},{$set:{"post.$.comment.detail.time":"News"}})
I am using the below code to insert data to mongodb
router.post('/NewStory', function (req, res) {
var currentObject = { user: userId , story : story , _id:new ObjectID().toHexString() };
req.db.get('clnTemple').findAndModify({
query: { _id: req.body.postId },
update: { $addToSet: { Stories: currentObject } },
upsert: true
});
});
This code is working fine if i remove the _id:new ObjectID().toHexString()
What i want to achieve here is that for every new story i want a unique _id object to be attached to it
What am i doing wrong?
{
"_id": {
"$oid": "55ae24016fb73f6ac7c2d640"
},
"Name": "some name",
...... some other details
"Stories": [
{
"userId": "105304831528398207103",
"story": "some story"
},
{
"userId": "105304831528398207103",
"story": "some story"
}
]
}
This is the document model, the _id that i am trying to create is for the stories
You should not be calling .toHexString() on this as you would be getting a "string" and not an ObjectID. A string takes more space than the bytes of an ObjectId.
var async = require('async'),
mongo = require('mongodb'),
db = require('monk')('localhost/test'),
ObjectID = mongo.ObjectID;
var coll = db.get('junk');
var obj = { "_id": new ObjectID(), "name": "Bill" };
coll.findAndModify(
{ "_id": new ObjectID() },
{ "$addToSet": { "stories": obj } },
{
"upsert": true,
"new": true
},
function(err,doc) {
if (err) throw err;
console.log(doc);
}
)
So that works perfectly for me. Noting the "new" option there as well so the modified document is returned, rather than the original form of the document which is the default.
{ _id: 55c04b5b52d0ec940694f819,
stories: [ { _id: 55c04b5b52d0ec940694f818, name: 'Bill' } ] }
There is however a catch here, and that is that if you are using $addToSet and generating a new ObjectId for every item, then that new ObjectId makes everything "unique". So you would keep adding things into the "set". This may as well be $push if that is what you want to do.
So if userId and story in combination already make this "unique", then do this way instead:
coll.findAndModify(
{
"_id": docId,
"stories": {
"$not": { "$elemMatch": { "userId": userId, "story": story } }
}
},
{ "$push": {
"stories": {
"userId": userId, "story": story, "_id": new ObjectID()
}
}},
{
"new": true
},
function(err,doc) {
if (err) throw err;
console.log(doc);
}
)
So test for the presence of the unique elements in the array, and where they do not exist then append them to the array. Also noting there that you cannot do an "inequality match" on the array element while mixing with "upserts". Your test to "upsert" the document should be on the primary "_id" value only. Managing array entries and document "upserts" need to be in separate update operations. Do not try an mix the two, otherwise you will end up creating new documents when you did not intend to.
By the way, you can generate an ObjectID just using monk.
var db = monk(credentials.database);
var ObjectID = db.helper.id.ObjectID
console.log(ObjectID()) // generates an ObjectID