Collection.findOne({_id: "stringidsdfdsfdsfds"}) is returns undefined - mongodb

I'm not new to Meteor, but been away for a couple of weeks due to working on other projects.
I'm now working on a Meteor project using React.
When I do this Collection.find({}).fetch() it returns this:
[
{
"_id": { "_str": "59d3b91d80f4f5eeb0162634" },
"title": "My first Post",
"content": "This is the body of the pst"
}
]
The only strange thing is the _id field.
But, when I do Collection.findOne({_id: "59d3b91d80f4f5eeb0162634" }), it returns undefined.
How can I do a .findOne() using the _id string as query parameter?

What you're seeing as _id's value is not a JSON object, but string representation of Mongo's ObjectID type, that's why your .findOne() fails to find it.
You should search it like this:
const _id = new Meteor.Collection.ObjectID('59d3b91d80f4f5eeb0162634');
Collection.findOne({ _id }); // same as { _id: _id }
By default, Meteor uses STRING method of _id generation, so it seems that this particular document has been inserted into collection another way.

Related

MERN stack, Mongodb updating all embedded document arrays with this value if they have a certain value

I am trying to updateMany() documents which are an array of documents, if they have a certain value. I am still learning mongodb and I know how to update all documents if they have this value with my new value. The problem I think I am having is that they are an array of documents so I need to go into each document find the field called courses go inside of it and find the document called name and then update it the value of name and I have been trying, but no luck. Also In the request I update the first collection no problem its when I get into the next collection where it does nothing like I already mentioned.
request.body.code = request.sanitize(request.body.code);
request.body.name = request.sanitize(request.body.name);
request.body.courses.forEach(course => {
course.code = request.sanitize(course.code);
course.name = request.sanitize(course.name);
});
let newValues = { $set: {"code": request.body.code, "name":request.body.name } };
result = await mongoClient.db(DB_NAME).collection("all_courses").updateOne(selector, newValues);
// Okay now try to update other collection of array documents which isnt working yet
selector = { "code": "PROG2700"};
newValues = { $set: {"code": request.body.code, "name": request.body.name } };
console.log("this is new values");
console.log(request.body.courses);
result = await mongoClient.db(DB_NAME).collection("technologies").updateMany(selector,newValues);
That is in my server doing the mongodb work and trying to update the documents.
let sendString:Object = {
"id": my,
"code": edit_Course?.code,
"name": state_category_name,
"courses":
[
{
"code": edit_Course?.code,
"name": state_category_name
}
]
}
That is what I am sending to the server as the request.body
{
"_id": "5fdaa52060689aa159e4122e",
"name": "Webpack",
"description": "Webpack is great",
"difficulty": 2,
"courses": [
{
"code": "PROG2700",
"name": "Client Side Programming"
},
{
"code": "PROG3017",
"name": "Full Stack Programming"
}
]
}
That is what the mongodb structure of each document looks like in the technologies collection that I am having trouble updating. Its the name field I need to update in every document under courses. Could anyone give me a helping hand, many thanks!
Your selector filter doesn't work for the technologies class because the matching code field is part of an array named courses. To account for this, the filter should look something like this:
{ "courses.code": "PROG2700" }
This is an example of querying a field in a document embedded in an array.
The next step is to update the right document in the array. This can be done in MongoDB using the positional operator $. The update document would look like this:
{ $set: { "courses.$.code": request.body.code, "courses.$.name": request.body.name }}
In this update document, the positional operator tells MongoDB to update the code and name fields of the first document in the courses array with a code of PROG2700.
Put together, the update might look like this:
filter = { "courses.code": "PROG2700" };
update = { $set: { "courses.$.code": request.body.code, "courses.$.name": request.body.name }};
result = await mongoClient.db(DB_NAME).collection("technologies").updateMany(filter,update);

MongoDB: update nested value in a collection based on existing field value

I want to update nested _ids over an entire collection IF they are of a type string.
If I have object that look like this...
user : {
_id: ObjectId('234wer234wer234wer'),
occupation: 'Reader',
books_read: [
{
title: "Best book ever",
_id: "123qwe234wer345ert456rty"
},
{
title: "Worst book ever",
_id: "223qwe234wer345ert456rty"
},
{
title: "A Tail of Two Cities",
_id: ObjectId("323qwe234wer345ert456rty")
}
]
}
and I want to change the type of the _Ids from string to ObjectId
how would I do that.??
I have done "this" in the past...But this is working on NON-nested item - I need to change a nested value
db.getCollection('users')
.find({
$or: [
{occupation:{$exists:false}},
{occupation:{$eq:null}}
]
})
.forEach(function (record) {
record.occupation = 'Reader';
db.users.save(record);
});
Any help - I am trying to avoid writing a series of loop on the app server to make db calls - so I am hoping for something directly in 'mongo'
There isn't a way of doing (non $rename) updates operations on a document while referencing existing fields -- MongoDB: Updating documents using data from the same document
So, you'll need to write a script (similar to the one you posted with find & each) to recreate those documents with the correct _id type. To find the subdocuments to update you can use the $type operator. A query like db.coll.find({nestedField._id: {$type: 'string' }}) should find all the full documents that have bad subdocuments, or you could do an aggregation query with $match & $unwind to only get the subdocuments
db.coll.aggregate([
{ $match: {'nestedField._id': {$type: 'string' }}}, // limiting to documents that have any bad subdocuments
{ $unwind: '$nestedField'}, // creating a separate document in the pipeline for each entry in the array
{ $match: {'nestedField._id': {$type: 'string' }}}, // limiting to only the subdocuments that have bad fields
{ $project: { nestedId: 'nestedField._id' }} // output will be: {_id: documentedId, nestedId }
])
I am trying to avoid writing a series of loop on the app server to make db calls - so I am hoping for something directly in 'mongo'
You can run js code directly on the mongo to avoid making api calls, but I don't think there's any way to avoid looping over the documents.

Get next item in MongoDB collection without ObjectId

I have access to a MongoDB collection but the entries their _id is a string, a url to be exact.
I want to retrieve the next document in a collection based on the previous _id. I looked around and I've seen it's possible using the ObjectID: Finding The Next Document in MongoDb.
My problem is that the database doesn't have ObjectID's in _id, there is also no field that could possibly be used as an alternative to ObjectID (f.e. a timestamp). So how would I retrieve the next document?
Edit: Added collection example
{ "_id": random.com,
"name": "Random",
},
{ "_id": example.com,
"name": "Example",
},
{ "_id": stack.com,
"name": "Stack",
}
If I have the _id "random.com", how do I retrieve the next document, in this case the one with _id "example.com"? I'm using pymongo.
cursor = db.coll.find({"_id": { "$gt": "the_url"}}).sort("_id").limit(1)
for doc in cursor:
print(doc['_id'])
see sort for how you could define order.
The index is alphabetical and we get next value of _id.
Still we can query for next inserted, that is about insertion time order, using sort("natural").
cursor = db.coll.find({"_id": { $gt":the_url"}}).sort("natural").limit(1)

MongoDB update collection's data

I try to update an MongoDB data by using this code:
db.medicines.update({"_id":"586a048e34e5c12614a7424a"}, {$set: {amount:'3'}})
but unfortantly the query does not recognize the selector "_id":"586a048e34e5c12614a7424a", even if its exists.
Its succsed when I change the key to another like: name,rate and etc..
there is a special way to use update with _id parameter?
Thanks a head.
_id will be the unique ObjectId that mongodb generates for every document before inserting it. The query dint work because _id is an ObjectId and "586a048e34e5c12614a7424a" is a String. You need to wrap _id with ObjectId().
If you're using mongodb query
db.medicines.update({
"_id": ObjectId("586a048e34e5c12614a7424a")
}, {
$set: {
amount: '3'
}
});
If you are using mongoose. You can use findByIdAndUpdate
db.medicines.findByIdAndUpdate({
"_id": "586a048e34e5c12614a7424a"
}, {
$set: {
amount: '3'
}
});

Mongodb: Update a field with data from a sub-sub field?

I'm trying to update a field in a collection with data from the same collection, but from a sub-sub field in it, and either can't get the syntax right, or I'm just doing it wrong.
I've spent quite some time now digging around here, but can't seem to get anywhere.
Here's the example structure of the users collection:
{
"_id": "12345qwerty",
"services": {
"oauth": {
"CharacterID": 12345678,
"CharacterName": "Official Username",
},
},
"name": "what I want to change",
"username": "OfficialUsername"
}
What I'm trying to do would be pretty trivial with SQL, ie: update all the display names to match a trusted source...
update users
set name = services.oauth.CharacterName;
...but I'm having trouble getting in MongoDB, and I have a feeling im doing it wrong.
Here's what i have so far, but it doesn't work as expected.
db.users.find().snapshot().forEach(
function (elem) {
db.users.update(
{ _id: elem._id },
{ $set: { name: elem.services.oauth.CharacterName } }
);
}
);
I can set the name to be anything at the base level, but can't set it to be something from the sublevel, as it doesn't recognise the sub-fields.
Any help would be greatly appreciated!
db.users.update({"services.oauth.CharacterName": {$exists: true}},{$set: {"name": "services.oauth.CharacterName"}},{multi:true})
I am setting name at the root of your document to be equal to the value in services.oauth.CharacterName in the sub sub document. multi = true will update multiple document, I am only updating documents that have the services.oauth.CharacterName value.