Replacing embedded document array with a string array in MongoDB - mongodb

In my collection, I have a users field as an array of the User collection.
So, it currently looks like this:
{ "name" : "Untitled", "users" : [ { "name" : "Ace Ventura", "datecreated" : "2012-10-05T23:55:56.940Z", "_id" : "740063fb-79c5-4f7f-96e1-907d6ffb1d16" } ], "datecreated" : "2012-10-05T23:55:56.954Z", "_id" : "e207eaea-89f7-48ae-8ba7-b6aa39db2358" }
I'd like to update it so that the array of User collection becomes just an array of the _id property of the User collection. Like so:
{ "name" : "Untitled", "users" : ["740063fb-79c5-4f7f-96e1-907d6ffb1d16" ], "datecreated" : "2012-10-05T23:55:56.954Z", "_id" : "e207eaea-89f7-48ae-8ba7-b6aa39db2358" }
How would I accomplish this?
Thanks in advance.

Alright, I figured it out.
Initially, I was thinking of doing something like this:
db.lists.update(
{},
{
$set: {
users: <oldusers._id>
},
});
However, as it turns out, you cannot reference the current document's properties from within an update().
But, it turns out we can use forEach():
db.lists.find().forEach(function (list) {
// Define length to ensure we have an array of users
var userLength = (list.users && list.users.length) || 0;
var (var i = 0; i < userLength; i++) {
// Ensure the current user object isn't null or undefined
if(list.users[i])
list.users[i] = list.users[i]._id
}
// Finally, save the list object back.
db.lists.save(list)
});
Thank, +gipset, for your answer here.

Related

MongoDB - change values from one ENUM type to another

I have MongoDB entries which looks like this:
{
"_id" : ObjectId("57288862e4b05f37bc6ab91b"),
"_class" : "mydomain.ScheduleAbsenceContainer",
"containerStart" : ISODate("2016-04-06T07:30:00Z"),
"containerEnd" : ISODate("2016-04-06T10:00:00Z"),
"scheduleIntervalContainerAbsenceType" : "SCHOOL",
"scheduleIntervalContainers" : [
{
"_id" : null,
"marker" : 6,
"containerType" : "SCHOOL",
}
]
}
and I will change all scheduleIntervalContainerAbsenceType from SCHOOL to SPARE_TIME and also all containerType's from SCHOOL to SPARE_TIME.
Is there a simple possibility to do this?
Below code does what you want. It updates all the documents which has the "SCHOOL" value for "scheduleIntervalContainerAbsenceType" keys.
db.collection_name.find({"scheduleIntervalContainerAbsenceType" : "SCHOOL"})
.forEach(function (doc) {
doc.scheduleIntervalContainers.forEach(function (sch) {
if (sch.containerType === "SCHOOL") {
sch.containerType="SPARE_TIME";
}
});
doc.scheduleIntervalContainerAbsenceType="SPARE_TIME";
db.collection_name.save(doc);
});
If you want to update all the documents without checking "scheduleIntervalContainerAbsenceType" value (still updating it to "SPARE_TIME") change your query like that.
db.collection_name.find({})
.forEach(function (doc) {
doc.scheduleIntervalContainers.forEach(function (sch) {
if (sch.containerType === "SCHOOL") {
sch.containerType="SPARE_TIME";
}
});
doc.scheduleIntervalContainerAbsenceType="SPARE_TIME";
db.collection_name.save(doc);
});

update multiple documents with sub array elements in mongodb without $ operator

I want to update the element of subarray with another element of same array index. Actually what mistake what I have done is typo mistake in column name (reviews, review) so want to update all reviews column with review. Can anybody give me the query to update this scenerio.
This is my document json
{
"_id" : ObjectId("57a5df273c6c00d1378b456d"),
"review_time" : ISODate("2016-02-06T12:59:19.000Z"),
"review" : "My name is Sandra P. and I am a satisfied customer. I've been working with eBrandz for a little more than two years and plan on keep doing so. They are always there whenever I have any concern and their approach is very professional. I would definitely recommend their services as I have seen great results.",
"rating" : 5,
"review_reply" : [
{
"author" : "http://new york.cylex usa.com/company/ebrandz inc 18441959.html",
"reply_time" : "1969-12-31",
"reviews" : "Sandra thanks for recommending ebrandz, appreciated."
},
{
"author" : "http://new york.cylex usa.com/company/ebrandz inc 18441959.html",
"reply_time" : "1969-12-31",
"reviews" : "Sandra thanks for recommending ebrandz, appreciated.1"
},
{
"author" : "http://new york.cylex usa.com/company/ebrandz inc 18441959.html",
"reply_time" : "1969-12-31",
"review" : "Sandra thanks for recommending ebrandz, appreciated22."
}
],
}
db.temp_reviews.find( {'review_reply.reviews' : {$exists : true} } ).forEach( function (doc) {
doc.review_reply.forEach(function (z) {
if(z.reviews){
z.review = z.reviews
delete z.reviews;
}
});
db.temp_reviews.save(doc);
});
Your were close, you just need to loop through your array, check if wrong field exist, create the field, delete the wrong field :
db.reviews.find({
'review_reply.reviews': {
$exists: true
}
}).forEach(function(doc) {
for (var i = 0; i < doc.review_reply.length; i++) {
if (doc.review_reply[i].hasOwnProperty("reviews")) {
doc.review_reply[i].review = doc.review_reply[i].reviews;
delete doc.review_reply[i].reviews;
}
}
db.reviews.save(doc);
});

How to return specific field's value in mongodb

how can I return a specific value for a specific document in MongoDB? For example, I have a schema that looks like:
{
"_id" : "XfCZSje7GjynvMZu7",
"createdAt" : ISODate("2015-03-23T14:52:44.084Z"),
"services" : {
"password" : {
"bcrypt" : "$2a$10$tcb01VbDMVhH03mbRdKYL.79FPj/fFMP62BDpcvpoTfF3LPgjHJoq"
},
"resume" : {
"loginTokens" : [ ]
}
},
"emails" : {
"address" : "abc123#gmu.edu",
"verified" : true
},
"profile" : {
"companyName" : "comp1",
"flagged" : true,
"phoneNum" : "7778883333"
}}
I want to return and store the value for profile.flagged specifically for the document with _id : XfCZSje7GjynvMZu7. So far I have tried:
db.users.find({_id:'myfi3E4YTf9z6tdgS'},{admin:1})
and
db.users.find({_id: 'myfi3E4YTf9z6tdgS'}, {profile:admin});
I want the query to return true or false depending on the assigned value.
Can someone help? Thanks!
MongoDB queries always return document objects, not single values. So one way to do this is with shell code like:
var flagged =
db.users.findOne({_id: 'myfi3E4YTf9z6tdgS'}, {'profile.flagged': 1}).profile.flagged;
Note the use of findOne instead of find so that you're working with just a single doc instead of the cursor that you get with find.
The correct answer here is the method .distinct() (link here)
Use it like this:
db.users.find({_id:'myfi3E4YTf9z6tdgS'},{admin:1}).distinct('admin')
The result will be: 1 or 0

Mongodb update subdocument inside array field of a collection

I have a mongodb collection like
{
"_id" : ObjectId("5375ef2153bb790b20d8a660"),
"association" : [
{
"count" : 3,
"name" : "hayatdediğin"
},
{
"count" : 2,
"name" : "sadecesenolsan"
},
{
"count" : 2,
"name" : "üslupnamustur"
}
],
"tag_count" : 4,
"tag_name" : "vazgeçilmezolan",
"variation" : [
{
"count" : 4,
"name" : "VazgeçilmezOlan"
}
]
}
Each collection consists of tag_name, tag_count, array field association and array field variation. For each name inside association, there exists a different document same as this document. I need to add new field "total_count" inside each association dictionary whose value equals the tag_count of the name by querying the database.
I tried this code but its not working
db.hashtag.find().forEach(function (doc) {
if (doc.association.length != 0 ) {
doc.association.forEach(function (assoc) {
db.hashtag.find({'tag_name': assoc.name}).forEach(function(tag){
assoc.total_count=tag.tag_count;
})
});
}
});
After modifying each doc you need to call save on the collection to commit the change.
Assuming you're doing this in the shell:
db.hashtag.find().forEach(function (doc) {
if (doc.association.length != 0 ) {
doc.association.forEach(function (assoc) {
db.hashtag.find({'tag_name': assoc.name}).forEach(function(tag){
assoc.total_count=tag.tag_count;
});
});
// Save the changed doc back to the collection
db.hashtag.save(doc);
}
});
To update doc in database you have to use db.hashtag.update, not db.hashtag.find. Find only retrieves document from db.
I changed the previous method of looping using forEach and then saved the doc at last and the code worked.
db.hashtag.find().forEach(function (doc) {
var array = doc.association;
if (array != undefined){
for(var i=0;i<array.length;i++)
{
var obj = db.hashtag.findOne({'name':array[i].name});
var count = obj.count;
doc.association[i].total_count = count;
db.hashtag.save(doc);
}
}
});

Update entry in an array or add to array if item doesn't exist [duplicate]

This question already has an answer here:
'upsert' in an embedded document
(1 answer)
Closed 8 years ago.
I have a collection that has a structure that looks like the following
{ "_id" : "MHBk8q96vpuRYrAdn",
"circles" : {
"guests" : 3,
"properties" : [
{
"position" : { "x" : 146, "y" : 70.5207970},
"name" : "circle-1"
},
{
"position" : { "x" : 200, "y" : 85},
"name" : "circle-2"
}
],
"tables" : 1
}
}
I need to be able to either update the position of circles.properties.position if it exists by name, or add a new entry if it does not. For example, update the position of "circle-1" since it exists, but add a new array item for "circle-3" with a name and position. Is it possible to achieve this? So far I have only been able to push onto the array using $push, and I have messed around with the $(query) operator with no success. Thanks.
Since MongoDB doesn't support upserts to arrays it can be tricky. You can try something like below:
var query = {};
new_circle = { "position" : { "x" : -1, "y" : -1}, "name" : "circle-1" };
db.foo.find(query).forEach(
function(doc) {
// Find index of 'circle-1'
i = doc.circles.properties.map(
function(el) { if (el.name == 'circle-1') return 1; else return -1;}
).indexOf(1);
// Update if circle-1 in circles-properties
if (i != -1) {
doc.circles.properties[i] = new_circle;
}
// If not push new
else {
doc.circles.properties.push(new_circle);
}
db.foo.save(doc);
}
)
Edit
If you cannot use save and update with upsert option replacing if-else block posted above with something like this should do the trick:
if (i != -1) {
db.foo.update(
{"_id" : doc._id, "circles.properties.name": "circle-1"},
{$set: {"circles.properties.$.position": new_circle.position}}
}
else {
db.foo.update(
{"_id" : doc._id},
{$push: {"properties": new_circle }}
)
}