How to update in nested schema in mongodb? - mongodb

I am working on meteor. I am trying to make blog with commmenting system.For post insertion my schema is this:
Posts.insert({
post:post,
author:username,
date:date,
createdAt:new Date(),
comment:{
commentBy:'',
commentMsg:''
},
userId:Meteor.userId()
})
At first the comment section will be blank. when user comment on particular post then comment section is filled.
I am trying to update this schema:
Posts.update(thisPost,{$addToSet:{comment.commentedBy:Name,comment.commentMsg:post}});
But its not working.How to do it right way??

for entering multiple comments the field should be an array.
comments:[{
Commentedby:String,
CommentedMsh:string
}]
You can either use $addtoset or $push,
db.update({_id:post._id},{$push:{comments:newComment}})
OR
db.update({_id:post._id}, { $addToSet: { comments : comment });

I think you need to put quotes around any dot references, like this:
Posts.update(thisPost,{$addToSet:{"comment.commentedBy":Name,"comment.commentMsg":post}});
The reason is because if you don't, your compiler will try and do object references locally, which is not what you want, if you pass it as a string, then Mongo will do it as expected.

There are two issues that I could find in your provided information.
First is that the comment property should be an array/collection, so you should initiate it as following (renamed to comments):
Posts.insert({
...
comments:[],
...
})
And second, and most important to answer you question, according to the documentation the first parameter on update should be either a selector, a ObjectID or a string id.
https://docs.meteor.com/api/collections.html#Mongo-Collection-update
So your update should look like this:
var comment = { commentBy: 'user-id', commentMsg: 'le-message' }
Posts.update(post._id, { $addToSet: { comments : comment });

Related

mongodb update an existing field without overwritting

{
questions: {
q1: "",
}
}
result after updating:
{
questions: {
q1: "",
q2: ""
}
}
I want to add q2 inside questions, without overwritting what's already inside it (q1).
One solution I found is to get the whole document, and modify it on my backend, and send the whole document to replace the current one. But it seems really in-effiecient as I have other fields in the document as well.
Is there a query that does it more efficiently? I looked at the mongodb docs, didn't seem to find a query that does it.
As turivishal said, you can use $set like this
But you also can use $addFields in this way:
db.collection.aggregate([
{
"$match": {
"questions.q1": "q1"
}
},
{
"$addFields": {
"questions.q2": "q2"
}
}
])
Example here
Also, reading your comment where you say Cannot create field 'q2' in element {questions: "q1"}. It seems your original schema is not the same you have into your DB.
Your schema says that questions is an object with field q1. But your error says that questions is the field and q1 the value.

mongodb adding values to array field

Hey guys not giving an example since the question is pretty straightforward.
I have a mongodb schema in which I have a field called Teamnames which is an array so
Teamnames: [String]
I am using body parser middleware to accept data from a form on my client side. There are about 10 different text boxes each having name as teamname1, teamname2, etc etc .
Whats the right syntax to update the mongodb field? I am doing findOneAndUpdate to retrieve the record from my collection after submitting the update and I wanted to update the Teamname array with the values. But I am kind of confused with the syntax and whats the right way to approach this. Can someone please help?
Try this:
const value = await YourModel.findByIdAndUpdate(id, {
$set: { teamnames: yourFormData }
},
{
new: true,
upsert: true,
});

MongoDB agregation: get next and previous element [duplicate]

I have a blog. On the individual post page I want to display a link to the previous, and if there is one, next post published in the bottom. The link should be the title of the specific post.
How do I do that the simplest way with Mongoose?
My current controller looks like this:
Post.findOne { slug : req.params.slug }, (err, post) ->
res.render "blog/show.jade", locals: title: "This post", post: post
And the schema looks like this:
PostSchema = new Schema(
title:
type: String
required: true
index: true
preamble: String
body: String
slug: String
createdAt: Date
updatedAt: Date
)
So let suppose you have schema like this:
{
_id,
text
}
I suppose that _id is mongo ObjectId, so we it contains post date and i can sort on it
Lets consider that i have opened current post with id equal to ObjectId( "43cc63093475061e3d95369d") (instead of this i will use curId) and i need to know next one and previous. Also lets consider that we need get all posts one by one ordered by created date descending:
Get next post you can like this:
db.posts.find({_id: {$gt: curId}}).sort({_id: 1 }).limit(1)
Get previous post you can like this:
db.posts.find({_id: {$lt: curId}}).sort({_id: -1 }).limit(1)
Few things:
If you don't use mongodb ObjectId above code will not work for you, but you can still use postDate instead of id and current post postDate instead of curId.
Take care about order when getting next/prev posts, to retrieve next post you need sort asc, to retrieve prev post you need sort desc.
I am not familiar with mongoose, so above scripts is mongodb shell scripts.
Find previous item:
Post.findOne({_id: {$lt: curId}}).sort({_id: -1}).exec(cb)
Find next item:
Post.findOne({_id: {$gt: curId}}).sort({_id: 1}).exec(cb)

Finding an object ID embedded in an array [duplicate]

I've found this question answered for C# and Perl, but not in the native interface. I thought this would work:
db.theColl.find( { _id: ObjectId("4ecbe7f9e8c1c9092c000027") } )
The query returned no results. I found the 4ecbe7f9e8c1c9092c000027 by doing db.theColl.find() and grabbing an ObjectId. There are several thousand objects in that collection.
I've read all the pages that I could find on the mongodb.org website and didn't find it. Is this just a strange thing to do? It seems pretty normal to me.
Not strange at all, people do this all the time. Make sure the collection name is correct (case matters) and that the ObjectId is exact.
Documentation is here
> db.test.insert({x: 1})
> db.test.find() // no criteria
{ "_id" : ObjectId("4ecc05e55dd98a436ddcc47c"), "x" : 1 }
> db.test.find({"_id" : ObjectId("4ecc05e55dd98a436ddcc47c")}) // explicit
{ "_id" : ObjectId("4ecc05e55dd98a436ddcc47c"), "x" : 1 }
> db.test.find(ObjectId("4ecc05e55dd98a436ddcc47c")) // shortcut
{ "_id" : ObjectId("4ecc05e55dd98a436ddcc47c"), "x" : 1 }
If you're using Node.js:
var ObjectId = require('mongodb').ObjectId;
var id = req.params.gonderi_id;
var o_id = new ObjectId(id);
db.test.find({_id:o_id})
Edit: corrected to new ObjectId(id), not new ObjectID(id)
Even easier, especially with tab completion:
db.test.find(ObjectId('4ecc05e55dd98a436ddcc47c'))
Edit: also works with the findOne command for prettier output.
You Have missed to insert Double Quotes.
The Exact Query is
db.theColl.find( { "_id": ObjectId("4ecbe7f9e8c1c9092c000027") } )
If you are working on the mongo shell, Please refer this : Answer from Tyler Brock
I wrote the answer if you are using mongodb using node.js
You don't need to convert the id into an ObjectId. Just use :
db.collection.findById('4ecbe7f9e8c1c9092c000027');
this collection method will automatically convert id into ObjectId.
On the other hand :
db.collection.findOne({"_id":'4ecbe7f9e8c1c9092c000027'}) doesn't work as expected. You've manually convert id into ObjectId.
That can be done like this :
let id = '58c85d1b7932a14c7a0a320d';
let o_id = new ObjectId(id); // id as a string is passed
db.collection.findOne({"_id":o_id});
I think you better write something like this:
db.getCollection('Blog').find({"_id":ObjectId("58f6724e97990e9de4f17c23")})
Once you opened the mongo CLI, connected and authorized on the right database.
The following example shows how to find the document with the _id=568c28fffc4be30d44d0398e from a collection called “products”:
db.products.find({"_id": ObjectId("568c28fffc4be30d44d0398e")})
I just had this issue and was doing exactly as was documented and it still was not working.
Look at your error message and make sure you do not have any special characters copied in. I was getting the error
SyntaxError: illegal character #(shell):1:43
When I went to character 43 it was just the start of my object ID, after the open quotes, exactly as I pasted it in. I put my cursor there and hit backspace nothing appeared to happen when it should have removed the open quote. I hit backspace again and it removed the open quote, then I put the quote back in and executed the query and it worked, despite looking exactly the same.
I was doing development in WebMatrix and copied the object id from the console. Whenever you copy from the console in WebMatrix you're likely to pick up some invisible characters that will cause errors.
In MongoDB Stitch functions it can be done using BSON like below:
Use the ObjectId helper in the BSON utility package for this purpose like in the follwing example:
var id = "5bb9e9f84186b222c8901149";
BSON.ObjectId(id);
For Pythonists:
import pymongo
from bson.objectid import ObjectId
...
for row in collectionName.find(
{"_id" : ObjectId("63ae807ec4270c7a0b0f2c4f")}):
print(row)
To use Objectid method you don't need to import it. It is already on the mongodb object.
var ObjectId = new db.ObjectId('58c85d1b7932a14c7a0a320d');
db.yourCollection.findOne({ _id: ObjectId }, function (err, info) {
console.log(info)
});
Simply do:
db.getCollection('test').find('4ecbe7f9e8c1c9092c000027');

Mongo update specific subdoc

I have the following mongo entry:
et = {
languages: [{
code: String,
title: String,
tools: [{
description: String,
mds: [ObjectId]
}],
}]
//some more stuff
}
I now need to update this object and add an new ObjectId to the mds array. I need to specify the language element via the code element and the tools entry via the description parameter.
So far I came up with the following update method with which I can update some element of the correct language entry:
ETs.find({
'_id':mdAttributes.etID,
'languages':{'$elemMatch':{'code':mdAttributes.language}}
},{
'$set':{
'languages.$.title':'update2.jpg'
}
});
However I do not know how add an query for the correct tool.
So what my set should make should be something like this:
ETs.find({
'_id':mdAttributes.etID,
'languages':{'$elemMatch':{'code':mdAttributes.language}}
},{
'$set':{
'languages.$.tools.$.mds': ["newId"]
}
});
Is there a way to achieve this in mongo?
Short answer, no. The positional operator doesn't currently work with nested arrays (https://jira.mongodb.org/browse/server-831).
You can do it nonetheless by setting the whole tools array entry (like you do on your first example, but for the tools array instead of the title field).