get the attributes of object recieved from mongodb - javascript

I have a alerts collection in my mongodb..
I wish to get the attributes of the object present in my alerts model, i have written the following code....
Alert.find({},function(err,alerts){
if(err)
console.log(err);
console.log(alerts);
alerts.forEach(function(result){
console.log(result.name);
console.log(result._id);
});
});
In first console, i am getting all the objects of alerts model,
but in second console it is 'Undefined' even result.name is present in the model..
But the _id is generated by mongodb itself and im able to get that id..
From 1st console:
{ __v: 0,
_id: 55128d3a1b35c366eb974285,
brand: 'SanDisk',
name: 'SanDisk Cruzer Blade 8 GB Pen Drives Black (Combo of 2)',
source:
{ name: 'Snapdeal',
productId: '141951',
inStock: true}
}
From 2nd console:
Undefined
From 3rd console
55128d3a1b35c366eb974285
Cannot able to get the problem, what is the correct way of doing this..
Thanks in advance

There is no problem here but you have to understand that MongoDB find() method returns a cursor to the documents that match the query criteria. So what you see in the console.log(alerts) is actually the cursor returned. When the find() method “returns documents,” the method is actually returning a cursor to the documents. So what you see in the first and third console outputs are cursor objects and properties.
You need to add a toArray() method to the resulting cursor from the Alert.find() operation, e.g.
Alert.find({}).toArray(function(err, alerts){
if(err)
console.log(err);
console.log(alerts);
alerts.forEach(function (result) {
console.log(result.name);
console.log(result._id);
});
});
The toArray() method returns an array that contains all the documents from a cursor. The method iterates completely the cursor, loading all the documents into RAM and exhausting the cursor.

I was using mongoose..
and the solution for the above is applying lean() function
i.e
Alert.find({}).lean().exec(function(err,alerts){
if(err)
console.log(err);
console.log(alerts);
alerts.forEach(function(result){
console.log(result.name);
console.log(result._id);
});
});

Related

Mongoose update map element inside array of document

as the title says, I want to update a value in a map inside an array in a document, Im using Mongoose. This is for a Discord bot, basically adding exp to a char every time user does a command, and it works, but it doesn't look right and I've been told it doesn't work sometimes:
This is how the maps inside the array look like:
click
// This gets the user document
let user = bot.userinventories.findOne({ userID: message.author.id })
// This searches the specific map I need by name
let check = await user.get('characters').filter(char => char.name === user.get('leveling'));
// This modifies the map in only 1 value
check[0].exp++;
// This removes the entire map and saves it again
await bot.userinventories.updateOne({ userID: message.author.id },
{ $pull:
{
characters: { name: check[0].name }
}
})
await bot.userinventories.updateOne({ userID: message.author.id },
{ $push:
{
characters: check[0]
}
})
As you can see, the part that doesn't seem right is having to entirely remove the map before saving it again, this also breaks any order by date. The big problem is that users have told me they've lost characters to this.
Another thing that sometimes fails is the 'let check' line, even tho it finds a map by the exact name (because of my code) it fails randomly like 1/20 times.
I found this which works, even tho it stills moves the object to the last place of the map, but it seems cleaner than what I had:
await bot.userinventories.updateOne(
{ userID: message.author.id, "characters.name": check[0].name },
{ $set: { "characters.$.exp" : check[0].exp } }
)
Edit: for it to not move the edited object to last place, I had to make a new variable or not use a variable for '"characters.$.exp" : ' for some reason

Mongoose does not remove all documents from collection

I have a mongoose Model, I try to remove all documents from a collection but after I run the code, the collection remains unmodified. Please see the code below:
return ProcessedStats.remove({}).then(function (d) {
console.log(d);
return ProcessedStats.find({}).count().then(function(c) {
console.log(c);
});
}).then(function() {
db.disconnect();
});
I call remove with an empty object, so to remove all documents, when I call find, I still have the count to 16000 documents.
What could be wrong?
Weird: if I do
find({})
and prin out data.length it equals 0, but if I do
.find({}).count()
it will equal 16000. What is wrong with the behaviour? What am I missing?
I think it was a caching issue, after I restarted the server, the count was ok

Parse Cloud Code - Why can't I delete a Parse.Role?

I can't figure out how to delete a Parse.Role in cloud code. The guide says they are subclasses of Parse.Object and have all the same methods. But I get the following error why I try to delete one:
Object [object Object] has no method 'destroy'
Parse.Cloud.afterDelete("Project", function(request) {
Parse.Cloud.useMasterKey();
var query = new Parse.Query(Parse.Role);
query.equalTo("name", "hasSound_" + request.object.id);
query.find().then(function(role) {
if(typeof role === 'undefined') {
console.log("role is undefined, cannot delete");
}
else {
role.destroy();
}
}).then(function(success) {
console.log("role deleted: hasSound_" + request.object.id);
}, function(error) {
console.log("error deleting role");
});
});
I had some console.log statements verifying the "name" is correct, so the query should be finding the right object. I'm not sure what else to try.
Also, my roles are named after the ids of Projects. So each Project has a role called "hasSound_[id of project]". When I delete a project, I no longer need the role associated with it. I mean I could leave the unused projects in the database, but that seems wasteful.
find() is fulfilled with an array of matching objects. Since your roles are unique, you can safely change find() to be first(). Or you can keep using find(), but treat the result as an array.

Mongo/Mongoose - markModified not working

I have the following query:
Section.find({"clause": sub.section}, function(err, docs){
var detail = parseInt(sub.detail);
docs[0].subClauses[0].additionalDetails[detail-1].percentile = sub.percentile;
docs[0].markModified("subClauses");
docs[0].save(function(err, doc){
if(err) { return callback(err) };
callback();
})
})
When I log the doc inside the .save function it appears to have saved successfully. However on querying the db elsewhere the save has not happened. The object its trying to save to is 3 deep like this:
[
{
"clause": "1",
"subClauses:
[
{
"clause":"1.1",
"additionalDetails:
[
{
"detail": "1",
"content": "whatever"
}
]
}
]
}
]
With several items inside each array.
Am I not able to save data to the nested array object using Mongo?
If I understand what you are trying to do, then I think what you are wanting to use is the Mongo Position Operator ($). This is used to index nested arrays in a document. In your current code you are only referencing the first object in the array. Using the position operator you will be able to reference other positions based of some other data, such as a query.
Here is the documentation for the operator: http://docs.mongodb.org/manual/reference/operator/update/positional/
And here is another Stack Overflow response which may help a bit also:
MongoDB $ operator

mongodb - capped collections with nodejs

I'm trying to set up and update some capped collections in MongoDB using Node.js (using the native MongoDB driver).
My goal is to, upon running app.js, insert documents into a capped collection, and also to update existing documents in a capped collection. Both of these are running on setInterval(), so every few seconds.
My questions:
I want to create a collection if the collection does not already exist, but if it does I want to insert a document into it instead. What is the correct way to check this?
With capped collections, should I even be explicitly creating them first before inserting anything into them? Normally I believe you can just insert things into a collection without explicitly creating them first, but in this case I need to ensure they are capped. Once the capped collection exists I know how to insert new documents into it, the problem is I need some way to handle the app being used for the first time (on a new server) where the collection doesn't already exist, and I want to do this creation using node and not having to jump into the mongo cli.
The trick here is that the collection needs to be capped, so I can do something like: db.createCollection("collectionName", { capped : true, size : 100000, max : 5000 } ). That will create the capped collection for me, but every time I call it it will call createCollection() instead of updating or inserting - if I call createCollection(), once the collection already exists, will it completely overwrite the existing collection?
An alternative is to turn a collection into a capped one with: db.runCommand({"convertToCapped": "collectionName", size: 100000, max : 5000 });. The problem with this is that node doesn't see runCommand() as a valid function and it errors. Is there something else that I'm meant to be calling to get this to work? It works in the mongo cli but not within node
What type of query do you use to find the first document in a collection? Again, within the mongo cli I can use db.collections.find() with some query, but within node it states that find() is not a valid function
How would I use collection.update() to add some new fields to an existing document? Lets say the document is some simple object like {key1: "value", key2: "value"} but I have an object that contains {key3: "value"}. Key 3 does not exist in the current document, how would I add that to what currently exists? This is somewhat related to #4 above in that I'm not sure what to pass in as the query parameter given that find() doesn't seem to play well with node.
Regarding your questions 1 - 4 about capped collections and creating them automatically, there are several ways to do this. On the one hand, you could run a script to initialise your database so that it has the capped collections available to your client when you run it for the first time. On the other hand, you could have a check to see if there are any documents in the given collection before inserting a document. If there are, you just insert your document and if there aren't, you create the capped collection and then insert the document as a callback to that function. It would work something like this:
var host = "localhost",
port = 27017,
dbName = "so";
var MongoClient = require('mongodb').MongoClient, Server = require('mongodb').Server;
var mongoclient = new MongoClient(new Server(host, port));
var db = mongoclient.db(dbName);
db.open(function(err, db) {
if(err) throw err;
// Capped collection.
var capped = db.collection('capped');
// Document to be inserted.
var document = { "foo": 1, "bar": 1 }
capped.find().count(function(err, count) {
if(err) throw err;
if (count === 0) {
console.log("Creating collection...");
db.createCollection("capped",
{ "capped": true,
"size": 100000,
"max": 5000 },
function(err, collection) {
if(err) throw err;
// Insert a document here.
console.log("Inserting document...");
collection.insert(document, function(err, result) {
if (err) throw err;
});
});
} else {
// Insert your document here without creating collection.
console.log("Inserting document without creating collection...");
capped.insert(document, function(err, result) {
if (err) throw err;
});
}
});
});
Regarding question 5, you can use findOne() to find a document in the collection, though this is not necessarily the first or last. If you want to guarantee the first or last, you can run a find() with a sort() and limit() of 1. Sorting by _id ascending should give you the first document. More information here.
// Sort 1 for ascending, -1 for descending.
capped.find().sort([["_id", 1]]).limit(1).nextObject(function(err, item) {
console.log(item);
});
Finally for question 6, you just use the $set operator with the update() method. More information here.
capped.update({ "foo": 1 }, { "$set": { "bar": 2 } }, {}, function(err, result) {
console.log(result);
});
Note that you can only update documents in place for capped collections, so you cannot do the insert of the extra field you mention. There are other restrictions enumerated here that you might want to be aware of.
[EDIT: Add updating nested fields in last document.]
If you want to update a nested field in the first or last document (use 1 or -1 in the sort, respectively), you can fetch the document, extract the _id, then perform an atomic update on that document. Something like this:
capped.find().sort([["_id", -1]]).limit(1).nextObject(function(err, item) {
if(err) throw err;
capped.update({ "_id": item._id },
{ "$set": { "timeCollected": 15, "publicIP.ip" : "127.0.0.1" }},
function(err, result) {
if(err) throw err;
console.log(result);
});
});
Note that even when updating a field that exists in a document in a capped collection, you need to ensure that the new value fits in the space allocated for the document. So, for example, updating a string value from "1" to "127.0.0.1" will not necessarily work.

Categories