Duplicate BinData Field on MongoDB console - mongodb

I have a document structure like this.
doc {
"_id": "customized str id"
"data": "BinData(0,"base64String");
}
db.test.find("_id":"1234-test").forEach(
function(doc) {
db.test.insert({_id":"1235-test"},{"data":doc.data});
}
);
I also tried.
db.test.find("_id":"1234-test").forEach(
function(doc) {
db.test.insert({_id":"1235-test"},{"data":new BinData(0,doc.data)});
or db.test.insert({_id":"1235-test"},{"data":{"$binary":doc.data,"$type":0}});
}
);
Result return except binary field.
Is there any way to copy binary field to duplicated document?
Thanks in advance.

You have two things wrong here.
First, insert() takes a single argument, which is the document to insert. (Did you perhaps want update/upsert?) So you want:
db.test.insert({_id":"1235-test", "data": doc.data})
Second, the data is already a binary BSON type when it's coming from the document, so you don't need to encode it or wrap it as BinData or anything.
> db.test.find({"_id": "1234-test"}).next().data
BinData(0,"base64String")
> typeof(db.test.find({"_id": "1234-test"}).next().data)
object
So, to copy it from one doc to a new doc:
db.test.find({"_id": "1234-test"}).forEach( function(doc) {
db.test.insert({"_id": "1235-test" , "data": doc.data})
})

Related

Mongodb use foreach on query and update results its results

I have a mongo collection where a field is supposed to point to another document's id in the same collection, but instead it is pointing to its "number". I need to perform an update on them but I'm having some problems on forming the query. Could you help me?
The structure of the document is like this:
{
"_id": "269410e2-cebf-40f1-a81f-fdce34185cdc",
"number": 1471,
"alternativeLocationId": "9871",
"locationType": "DUMMY"
},
{
"_id": "2945b24a-b82f-45a9-ad06-a884379b5597",
"number": 9871,
"locationType": "MAIN"
}
So as asked, I'd need to make document with number 1471 "alternativeLocationId" to be "2945b24a-b82f-45a9-ad06-a884379b5597" instead of 9871 (Note that the referenced documents are not locationType "DUMMY" nor have this alternativeLocationId field).
The query I've done so far goes like this, but when executed its not doing any changes:
db.location.find({alternativeLocationId: {$exists:true}}).forEach(
function (loc) {
var correctLocation = db.location.findOne({number: loc.alternativeLocationId});
db.location.update(
{_id: loc._id},
{$set: {alternativeLocationId: correctLocation._id} }
);
}
);
As mentioned by user20042973 the issue was the type mismatch between alternativeLocationId and locationNumber, after converting the value to int when looking for it, it works perfectly.

Mongo adding a field to a specific object in an array of objects using updateOne during a bulkUpdateOps

Use case
Adding a field to a specific object in an array of objects using updateOne during a bulkUpdateOps
Blockers
I have been unable to find a way to identify and update a specific object in the subdocument array of a specific record.
I only have access to this DB through MongoDB Compass, and I plan to use the provided mongosh tool.
Data example
Our purchaseorders model looks like this:
{
_id: uuid,
...rest,
documents:[
{
_id:uuid,
forignKey2:string (optional),
keyIWantToAdd:string (optional),
...rest
}
]
}
So if I have
{
_id:*1,
documents:[
{
_id:*2,
forignKey2:'no-test',
...rest
},
{
_id:*3,
forignKey2:'test',
...rest
},
]
}
I want to add a key and value like this (really I'm willing to do anything to set these values, this is just the closest I have been able to get):
var bulkUpdateOps = db.purchaseorders.initializeOrderedBulkOp();
bulkUpdateOps.find('*1').updateOne({
$set:{
documents.[index of document object with forignKey2:'test' or _id:*3 whichever is easier].keyIWantToAdd:'valueIWantToAdd'
}
})
bulkUpdateOps.execute();
Any help or suggestions would be greatly appreciated.
#rickhg12hs posted exactly what I was looking for. For anyone else using mongodb.com/docs/manual/reference/method/Bulk.find.arrayFilters the bulk find is being ran on an array of objects like this: { grades:[ { grade: 85, mean: number } ] }

Cast MongoDB $objects ($oid, $date, $binary...) to Mongoose objects

Well, I have used MongoDB in a while but I don't know how to handle this situation.
The scenario is: I have data inserted in MongoDB. I have exported the data in JSON format, and it is something like:
[
{
"_id": { "$oid": "60ff324f41c4d5b96054390d" },
"field": {
"due_date": { "$date": "2021-11-03T00:09:18.271Z" }
}
}
]
You can see that :
_id is { "$oid": "60ff324f41c4d5b96054390d" } and
date is { "$date": "2021-11-03T00:09:18.271Z" }.
So, the problem is trying to insert in another DB using Mongoose. I want to test some funcionality isolated so I wan't these values in other environment, so I have used insertMany() with the JSON previously exported.
(Maybe there is a more elegant way to import a JSON file but is only for testing purposes)
await model.insertMany(JSON.parse(fs.readFileSync('./data.json').toString()))
But the problem is here: It throws an error because my schema says that _id is an ObjectId and due_date is a Date object but they are actually read as objects: {$oid: ""} and {$date: ""}
ValidationError: model validation failed: _id: Cast to ObjectId failed for value "{ '$oid': '60ff324f41c4d5b96054390d' }" (type Object) at path "_id", field.due_date: Cast to date failed for value "{ '$date': '2021-11-03T00:09:18.271Z' }" (type Object) at path "field.due_date"
So the question is: Is there any way to cast the $oid and $date objects using mongoose while inserting?
Also, I have managed to insert the values using a very ugly script iterating over each value and checking if the object is $oid or $date and modifying the values... but it works.
So the question is not: "Is there a workaround to do this?" but "Is there a way to do it directly with mongoose functions as insertMany and casted automatically?"
Thanks.
The {"$oid": ...} and {"$date":...} constructs are MongoDB extended JSON notation, since JSON does not have any type for Date or ObjectId.
In order to insert those values, you will need to use a JSON parser that knows about this extended format.
One possibility is the json_util that is included with bson.
Or you can use mongoimport to read the JSON file and do the inserts for you.

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.

duplicate mongo record in same collection

In mongo I have a collections with records. These record are very complex. Now I would like to duplicate one of them.
I can easily select the one
mongo> var row = db.barfoo.find({"name":"bar"});
Now I actually don't know what to do. I don't know what is in row because I cannot find a way to print its content. How can I change specific properties and finally insert this modified row again
mongo> db.barfoo.insert(row);
thnx
You must change value _id - generate new:
var row = db.barfoo.findOne({"name":"bar"});
row._id = ObjectId();
db.barfoo.insert(row);
Good Luck!
I am going to assume that you're working directly inside the mongo shell.
Once you have your document (not a row :P ), you'd modify the properties in the same way you would a normal JavaScript object:
var doc = db.barfoo.findOne( { "name": "bar" } );
doc.name = "Mr Bar";
Note that the find() command returns a cursor, so if you're looking to extract a single document, you should use the findOne() function. This function returns a single document.
If you are interested in duplicating numerous documents, you can use the find() function and iterate over the cursor to retrieve each document:
db.barfoo.find( { "name": "bar" } ).forEach( function( doc ){
doc.name = "Mr Bar";
}
After you change the relevant properties, you can use the insert/save methods to persist the data back to mongo. Don't forget to change/delete the _id attribute so that you'll actually create a new document.
As a side note, in order to view the contents of an object in the mongo shell, you can use the print() function. If you want a more visually appealing output, you could use printjson().