Change _id value from a number to ObjectId()? [duplicate] - mongodb

This question already has answers here:
How to update the _id of one MongoDB Document?
(7 answers)
Closed 8 years ago.
I have a collection (510 documents) where _id are numbers :
{ "_id" : "1",
"name" : "eric" }
{ "_id" : "2",
"name" : "tom" }
....
and I want to change their values to ObjectId() to be like this:
{ "_id" : ObjectId("53849e258bf3be07804a00d0"),
"name" : "eric" }
{ "_id" : ObjectId("53849e388bf3be07804a00d1"),
"name" : "tom" }
....
so I tried:
db.contacts.find().forEach(function(doc) {
db.contacts.update(
{ "_id": doc._id },
{ "$set": { "_id": ObjectId()} }
);
})
but it doesn't work, I got like result:
Mod on _id not allowed
Thank you.

You cannot change the _id of an Object in a collection once it is created (it is not allowed by mongodb at all). However you could copy the full content of the object execpt of the _id and add your new _id with the ObjectId and insert it into your collection. Afterwards you can remove all the Objects where the _id is a number. It's a bit more complicated but the result is the same (and it works).
Have a look here.

Related

get data from nested documents in mongodb / find is not working [duplicate]

This question already has answers here:
Retrieve only the queried element in an object array in MongoDB collection
(18 answers)
Closed 4 years ago.
i have data in my collection called users like this
{
"_id" : ObjectId("5aeffdb80e006205640052ff"),
"name" : "KOTA AMBON",
"email" : "ambon#gmail.com",
"password" : "$2y$10$VVaGAVniUbgBnDw6x5yZ0uAvJDGa5ekmVPJk/1Lubz5yKzZ75opo2",
"updated_at" : ISODate("2018-05-07T07:18:16Z"),
"created_at" : ISODate("2018-05-07T07:18:16Z"),
"dinas" : [
{
"id" : "5aeffdb80e006205640052ff_5af0101d0e00620564005307",
"nama_dinas" : "dinas perikanan",
"deskripsi_dinas" : "dinas untuk ikan",
"keyword" : "ikan"
},
{
"id" : "5aeffdb80e006205640052ff_5af010390e00620564005308",
"nama_dinas" : "dinas perhubungan",
"deskripsi_dinas" : "dinas untuk hubungan",
"keyword" : "jalan"
}
]
}
I want to get dinas attribute where id is `"5aeffdb80e006205640052ff_5af0101d0e00620564005307"
I had using function db.users.find('dinas.id', '5aeffdb80e006205640052ff_5af0101d0e00620564005307') but the output still called all elements in dinas like i wrote above.
Did i do something wrong?
Filtering in MongoDB (using find) will always return entire document, you have to add projection as a second argument of a find method like below:
db.users.find({"dinas.id": "5aeffdb80e006205640052ff_5af0101d0e00620564005307"},
{ "dinas": { $elemMatch: { id: "5aeffdb80e006205640052ff_5af0101d0e00620564005307" } } });
$elemMatch in projection will filter your nested array and return first matching element (that's fine assuming your ids are unique)
You need to take a look at array querying. The problem is that your dinas is a array of objects, and you're trying to query it as a object directly.
Probably $elemMatch will help you. Something like:
db.users.find({
dinas: {
$elemMatch: {
id: 'youridhere'
}
}
});

Single Element of embedded Array Projection [duplicate]

This question already has answers here:
Project first item in an array to new field (MongoDB aggregation)
(3 answers)
Retrieve only the queried element in an object array in MongoDB collection
(18 answers)
Closed 4 years ago.
{
"_id" : ObjectId("5b04e9d891081234f8b69199"),
"simpleType" : "somethingSomething",
"embeddedArray" : [
{
"type" : "theTypeIWant",
"data" : [...]
},
{
"type" : "notThatOne",
"data" : [...]
},
{
"type" : "notThatOne",
"data" : [...]
},
{
"type" : "notThatOne",
"data" : [...]
},
{
"type" : "notThatOne",
"data" : [...]
}
]
}
I have a collection which the documents are structured like my sample above. I already started with an aggregation to match the type I want, but I get the whole array with it which I don't want.
db.collection.aggregate(
[
{$project: {"simpleType" : 1, "embeddedArray.type": 1, "embeddedArray.data": 1}},
{$match: {"embeddedArray.type" : "theTypeIWant"}}
]
)
Is there a way to get only that element of the embeddedArray, that matches the type I am searching for, for my projection?
I cannot guarantee that the element with the type I am searching for will always be the first element in my embedded array.
I would like to have a result set like following:
{
"simpleType" : "somethingSomething",
"type": "theTypeIWant",
"data": [...]
}
or:
{
"simpleType" : "somethingSomething",
"embeddedArray":{
"type": "theTypeIWant",
"data": [...]
}
}

Change document structure in mongodb with the mongo shell [duplicate]

This question already has an answer here:
Reshape all the documents in the collection
(1 answer)
Closed 6 years ago.
I have a document structure in mongodb and i want to change it for all my documents without using aggregate function like this response but by creating a specific function, and have a result from that :
{
"_id" : ObjectId("String"),
"content" : {
"href" : "String",
"text" : "String",
"code" : "String "
}
}
to that :
{
"_id" : ObjectId("String"),
"href" : "String",
"text" : "String",
"code" : "String "
}
Any suggestions please. Thank you.
If you do not fancy aggregation (or your content's content may differ across documents) you can also use
db.coll.find().forEach(function (d) {
db.coll.update({
_id : d._id
}, {
$set : d.content,
$unset : {
'content' : 1
}
})
});
The easiets way to do it is to use aggregation framework.
Then save output into newCollection and after verification you can delete old one and rename created one.
db.collection.aggregate([{
$project : {
_id : 1,
href : "$content.href",
text : "$content.text",
code : "$content.code",
}
}, {
$out : "newCollection"
}
])

MongoDB fields limitation in array [duplicate]

This question already has answers here:
Retrieve only the queried element in an object array in MongoDB collection
(18 answers)
Closed 8 years ago.
I am looking for a way - and dont even now if this is possible - just to return a part of a list saved in mongodb.
Lets have a look in my currently document:
{
_id : 'MyId',
name : 'a string',
conversations : [
{
user : 'Mike',
input : 'Some input'
},
{
user : 'Stephano',
input : 'some other input'
}
]
}
What I now want to do is smth like this:
var myOutput;
myOutput = db.my_collection.find(
{
_id : 'MyId',
'conversations.user' : 'Mike'
}, {
_id : 1,
name : 1,
conversations : {
$where : {
user : 'Mike'
}
}
});
Goal is it just to get back the conversation array item where user has the value Mike.
Is this still possible in MongoDB ? didn't found any reference in the documentation for the field limitations in mongoDB.
Use the $ positional operator in a projection:
> db.my_collection.find({ "_id" : "MyId", "conversations.user" : "Mike" },
{ "_id" : 1, "name" : 1, "conversations.$" : 1 })
{
"_id" : 'MyId',
"name" : 'a string',
"conversations" : [
{ "user" : 'Mike', "input" : 'Some input' }
]
}
This projects only first matching array element.
Are you aware of the aggregation pipeline?
db.my_collection.aggregate([
{ "$match": { "_id": "MyId"}}, { "$unwind": "$conversations"},
{ "$match": {"conversations.user": "Mike"}}
])
Output
{
"_id" : "MyId",
"name" : "a string",
"conversations" :
{
"user" : "Mike",
"input" : "Some input"
}
}

Getting only Sub Elements [duplicate]

This question already has answers here:
Retrieve only the queried element in an object array in MongoDB collection
(18 answers)
Closed 8 years ago.
If I have the following document
{
"_id" : ObjectId("54986d5531a011bb5fb8e0ee"),
"owner" : "54948a5d85f7a9527a002917",
"type" : "group",
"deleted" : false,
"participants" : [
{ "_id": "54948a5d85f7a9527a002917", "name": "user1" },
{ "_id": "5491234568f7a9527a002918", "name": "user2" },
{ "_id": "5491234568f7a9527a002918", "name": "user3" },
{ "_id": "1234567aaaa7a9527a002917", "name": "user2" }
]
}
How would I get all records where name = 'user2'?
I'm trying the followoing:
db.users.find({ _id: ObjectId('54a7103b1a57eee00bc0a9e4') },
{ 'participants.$.name': 'user2') }).pretty()
...and I get the following:
error: {
"$err" : "Can't canonicalize query: BadValue Positional projection 'participants.$.name' does not match the query document.",
"code" : 17287
}
Though the positional operator($) would give you the first matching element from the participant array. If you need all the participants in with the name user2, you need to aggregate the results.
Match the document with the required _id.
Use the redact operator to only keep all the sub documents that have
participants, who have their name as user2.
Code:
var search = "user2";
db.users.aggregate([
{$match:{"_id":ObjectId("54986d5531a011bb5fb8e0ee")}},
{$redact:{$cond:[{$eq:[{$ifNull:["$name",search]},search]},
"$$DESCEND",
"$$PRUNE"]}},
{$project:{"participants":1,"_id":0}} // set _id:1, if you need the _id.
])
o/p:
{
"participants" : [
{
"_id" : "5491234568f7a9527a002918",
"name" : "user2"
},
{
"_id" : "1234567aaaa7a9527a002917",
"name" : "user2"
}
]
}
Coming to your query,
db.users.find({ _id: ObjectId('54a7103b1a57eee00bc0a9e4') },
{ 'participants.$.name': 'user2'}).pretty()
The positional operator can be applied only on the array, that is referred in the query document of the find function. The above query document doesn't have a reference to the array named participants and only refers to the _id field to match a document. Hence you get the error.
From the docs,
The field being limited must appear in the query document
So, changing the query to include the participants array in the query document would fix the error.
db.users.find({ "_id":ObjectId('54a7103b1a57eee00bc0a9e4'),
"participants.name": "user2"
},
{"participants.$.name":"user2"}).pretty()
But it would return you only the first participant that has matched the criteria in the query document.
From the docs,
Use $ in the projection document of the find() method or the findOne()
method when you only need one particular array element in selected
documents.
o/p:
{
"_id" : ObjectId("54986d5531a011bb5fb8e0ee"),
"participants" : [
{
"_id" : "5491234568f7a9527a002918",
"name" : "user2"
}
]
}