MongoDb: Accessing Collection and console log Object - node.js

I am trying to access a MongoDB Collection and I want to console.log a Object from this Collection.
I connect to my MongoDB as follows:
async function main(){
/**
* Connection URI. Update <username>, <password>, and <your-cluster-url> to reflect your cluster.
* See https://docs.mongodb.com/ecosystem/drivers/node/ for more details
*/
const uri = process.env.DB_Port;
const client = new MongoClient(uri,{ useNewUrlParser: true, useUnifiedTopology: true});
try {
// Connect to the MongoDB cluster
await client.connect();
// Make the appropriate DB calls
await listDatabases(client);
} catch (e) {
console.error(e);
} finally {
await client.close();
}
}
main().catch(console.error);
async function listDatabases(client){
databasesList = await client.db().admin().listDatabases();
console.log("Databases:");
databasesList.databases.forEach(db => console.log(` - ${db.name}`));
};
This console logs:
Databases:
- radiototem
- test
- admin
- local
Now I want to access the collection test and console log everything that is inside it. How can I achieve this?
Best regards

In order to get items from MongoDB, you first need to access the collection in which they are stored. Collections in MongoDB are basically the same as tables in SQL.
To get a collection, call the .collection() function on your DB object you get from client.db() with the name of your collection like this:
client.db().collection('test'); // This gives you the collection "test"
If you want to get items from a collection, you can use the .find() method. You can pass it a query parameter which is an object where you define, which items should be selected based on their properties.
Example, get all users named peter from the users collection:
const db = client.db();
const users = db.collection('users');
const usersNamedPeterCursor = users.find({ name: 'Peter' });
Now if you want to get all items from a collection, you can simply use the find method without the query parameter. This will return all items from the collection.
The find method returns a Cursor object which lets you interact with the returned data. You can call methods on the Cursor object like max(), min(), toArray(), each() and many more.
So, if you want to console.log every item in your collection you can do it like this:
client.db().collection('test').find().each(function(error, item) {
// console .log your item or do something else with it
});

Related

MongoDB not saving value, call responds fine on postman, no errors

I have a NodeJS backend call with MongoDB. This particular api call was working fine for a long time, and when testing out something on the frontend, I realized the call was not going through. I've checked the routes, controller, index files, and tested the call through Postman which works fine, no errors, and even returns an ObjectId (which means it must be interacting with the database, right?). However, when I search the mongo shell nothing comes back, which tells me it is not saving. I cannot find anything wrong and get no errors anywhere along the way. I checked on MongoDB Atlas, the collection only has 4kb of data so it is not that it is 'too full' and have tested all the other api calls (get, patch, delete) which work fine and have no issues like this in my other collections.
Even weirder, during the save call I push the ID to 2 other collection's documents as a ref. The Mongo shell does show that the new Id is populating to the other documents, but yet it is not saving the actual document... which should be happening prior to the push and needs to happen in order to get the ObjectId
Below is the controller for adding a new Visit document, the route for it, and the response from postman. I really have no idea of how else to determine what is taking place.
Controller
exports.addVisit = async (req, res) => {
const hoursValue = getTotalHours(req.body.visitStart, req.body.visitEnd)
try {
const visit = new Visit({
totalHours: hoursValue,
user: req.body.user,
client: req.body.client,
visitStart: req.body.visitStart,
visitEnd: req.body.visitEnd,
location: req.body.location
});
const user = await User.findById(req.body.user);
const client = await Client.findById(req.body.client);
visit.user = user._id
visit.client = client._id
visit.save();
user.visits.push(visit._id);
user.save();
client.visits.push(visit._id);
client.save();
console.log(visit)
console.log(user)
console.log(client)
res.status(201).send(visit);
} catch (error) {
res.status(400)
res.send({ error: "Error adding visit", error})
}
}
Route
router.route("/visits").post(addVisit)
Postman call to: http://localhost:5000/visitapi/visits
{
"client": "6205a8313fe12d6b4ec354c4",
"location": "Home",
"user": "62410a1dcaac9a3d0528de7a",
"visitStart": "2022-10-12T17:00:00.000Z",
"visitEnd": "2022-10-12T19:00:11.000Z"
}
Postman response
{
"client": "6205a8313fe12d6b4ec354c4",
"user": "62410a1dcaac9a3d0528de7a",
"location": "Home",
"visitStart": "2022-10-12T17:00:00.000Z",
"visitEnd": "2022-10-12T19:00:11.000Z",
"totalHours": 2,
"goals": [],
"id": "635302bb48e85ff6ad17ee59"
}
NodeJs console logging the same new document with no errors:
{
client: new ObjectId("6205a8313fe12d6b4ec354c4"),
user: new ObjectId("62410a1dcaac9a3d0528de7a"),
location: 'Home',
visitStart: 2022-10-12T17:00:00.000Z,
visitEnd: 2022-10-12T19:00:11.000Z,
totalHours: 2,
_id: new ObjectId("635302bb48e85ff6ad17ee59"),
goals: []
}
MongoShell showing the Client collection document stored the new Visit document Id:
visits: [
ObjectId("6257158d157e807e51c7e009"),
ObjectId("62fd852a252b83f4bc8f9782"),
ObjectId("63056cee252b83f4bc8f97e9"),
ObjectId("634ee01ec582da494032c73e"),
ObjectId("634ee09cc582da494032c7aa"),
ObjectId("634ee3d6ddbe3f7e6641d69e"),
ObjectId("634efcf1ddbe3f7e6641d6f9"),
ObjectId("634efdd3ddbe3f7e6641d71b"),
ObjectId("635029937da8972360d907c1"),
ObjectId("6350a0e37da8972360d9084f"),
ObjectId("635302bb48e85ff6ad17ee59") //_id matches the same returned by Postman/ NodeJS
],
Again, everything goes through with no errors on postman or the front or back end, and the backend even logs the returns the new document but no new document is being saved to the DB unless I manually pass it in the Mongosh shell, and only for this one collection. Totally lost, I'd appreciate any guidance on how to explore/ resolve this. Thanks
Edited to include the solution based on the discussion in comment
The problem could be in the mongoose schema. If the property names do not match, mongoose will simply ignore the mismatched properties.
Previous answer
Those mongodb calls are expected to be async. You might want to add await to all those.
visit.user = user._id
visit.client = client._id
await visit.save(); // <- this
user.visits.push(visit._id);
await user.save(); // <- this
client.visits.push(visit._id);
await client.save(); // <- and this

firestore not returning any indication that a new document add was succesful or not

I think this is not right, or i am the one not doing it well, so when i add a new document to the firestore collection, i can use the ref to get the id, but when i pass a wrong collection name, I still get the same response, why isn't firestore throwing an error.
async function addDoc(collection, data) {
try {
const db = admin.firestore();
const ref = await db.collection(collection).doc() //add(data);
ref.set(data);
console.log("Document successfully added!", ref);
}
catch (err) {
console.log("Error adding document: ", err);
}
}
i want to know why this is behaving like this, and how to detect if the new document was created. Thanks
Collections are created on demand, when you first write a document to them. So what you call "a wrong collection name" Firestore is likely interpreting that is an instruction to create a new collection with that name.

How to use Mongo Bulk together with multi-document transactions in NodeJs?

I want to run a bulk operation in mongo but at the same time run it inside a multi document transaction. I am using Meteor running the NodeJs driver of MongoDb.
According to the MongoDB documentation (https://docs.mongodb.com/manual/reference/method/Bulk/) it should be possible to combine Bulk and multi-document transactions. However, I have not been able to solve this.
My problem is how to pass the session object to the Bulk operations. For non-bulk operations we just pass it as an options object const options = {session: session}. I have tried to pass it in several ways but nothing seems to work.
How should the session object be used in Bulk operations?
Below is a simple example of what I am trying to achive.
const getMongoClient = function() {
const { client } = MongoInternals.defaultRemoteCollectionDriver().mongo;
return client;
}
const session = client.startSession();
try {
session.startTransaction();
const bulk = someCollectionToBulkWrite.rawCollection().initializeOrderedBulkOp(); // Pass the session here?
const dataInsert = someCollection.insert(someObject, {session}).await().value;
const dataInsertOtherDocument = someOtherCollection.insert(someOtherObject, {session}).await().value;
bulk.find( { _id: someId } ).update( { $set: { testField: 3}}); //Or pass the session here?
bulk.find( { _id: someOtherId } ).update( { $set: { testField: 3}});
bulk.execute().await(); // Or pass the session here?
session.commitTransaction().await();
} finally {
session.endSession();
}
I checked the code for the MongoDB driver for NodeJS and more specifically for the Bulk API (https://github.com/mongodb/node-mongodb-native/blob/master/lib/bulk/common.js)
The definition of the execute methods looks as follows:
execute(_writeConcern, options, callback);
The session should thus be passed as the second argument to execute. In the example provided in the question that would look like this:
bulk.execute(null, {session}).await();

A possible timeout in find() method - mongoDb

I'm writing a Node.js project using MongoDb and socket.io. I met one problem. I have a collection called rooms rooms = db.collection('rooms');
Here's my code when i'm trying to join a room
rooms.find({name: roomName}).limit(1).toArray()
.then(function (res) { //if successful
res = res[0]; //i get my username
If there's a room with the given id I connect to it, otherwise it must be created.
But when i create a new room i get undefined, but when I connect the second time (the room already exists) it's all ok, i get all the information. So when I create a room and connect to it, I don't get my username, but when it's created (I'm connecting to it the second time) it displays me the method.
var mongo = require('mongodb').MongoClient - module,
function http(io) { mongo.connect(config.mongodb_url)
.then(function (db) { ...
-connection,
"mongodb version": "^2.1.7"
This is how i create a room
rooms.findOneAndUpdate(
{name: roomName},
{$addToSet: {users: uuid}}
).then(users_update).catch(logger.error);
}).catch(logger.error);
I'm wondering if there are some timeout in the find method? Or where can be here the mistake?
I found the answer. It was just that simple: I added { upstream: true } to my findOneAndUpdate() function.

Meteor cannot retrieve data from MongoDB

Pretty straightforward and without any sort of configuration ->
In the project directory I entered the command:
$ meteor mongo to access the mongodb
From there (mongo shell), I switched to db meteor using the command use meteor then entered some basic data to test:
j = { name: "mongo" }
k = { x: 3 }
db.testData.insert(j)
db.testData.insert(k)
I checked and got results by entering: db.testData.find()
Here's my meteor code provided that mongodb access is only required on the client:
if (Meteor.isClient) {
Template.hello.greeting = function () {
return "Welcome to test.";
};
Template.hello.events({
'click input' : function () {
// template data, if any, is available in 'this'
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
});
Documents = new Meteor.Collection('testData');
var document = Documents.find();
console.log(document);
var documentCbResults = Documents.find(function(err, items) {
console.log(err);
console.log(items);
});
}
Upon checking on the browser and based on the logs, it says undefined. I was unsuccessful from retrieving data from mongodb and showing to the client console.
What am I missing?
For this answer I'm going to assume this is a newly created project with autopublish still on.
As Christian pointed out, you need to define Documents on both the client and the server. You can easily accomplish this by just putting the collection definition at the top of the file or in another file which isn't in either of the server or client directories.
An example which prints the first two test documents could look like this:
Documents = new Meteor.Collection('testData');
if (Meteor.isClient) {
Template.hello.greeting = function () {
return "Welcome to apui.";
};
Template.hello.events({
'click input' : function () {
var documents = Documents.find().fetch();
console.log(documents[0]);
console.log(documents[1]);
}
});
}
Note the following:
The find function returns a cursor. This is often all you want when writing template code. However, in this case we need direct access to the documents to print them so I used fetch on the cursor. See the documentation for more details.
When you first start the client, the server will read the contents of the defined collections and sync all documents (if you have autopublish on) to the client's local minimongo database. I placed the find inside of the click event to hide that sync time. In your code, the find would have executed the instant the client started and the data probably would not have arrived in time.
Your method of inserting initial items into the database works (you don't need the use meteor by the way), however mongo will default to using an ObjectId instead of a string as the _id. There are subtle ways that this can be annoying in a meteor project, so my recommendation is to let meteor insert your data if at all possible. Here is some code that will ensure the testData collection has some documents:
if (Meteor.isServer) {
Meteor.startup(function() {
if (Documents.find().count() === 0) {
console.log('inserting test data');
Documents.insert({name: "mongo"});
Documents.insert({x: 3});
}
});
}
Note this will only execute if the collection has no documents in it. If you ever want to clear out the collection you can do so via the mongo console. Alternatively you can drop the whole database with:
$ meteor reset
It's not enough to only define collections on the client side. Your mongo db lives on the server and your client needs to get its data from somewhere. It doesn't get it directly from mongodb (I think), but gets it via syncing with the collections on the server.
Just define the Documents collection in the joint scope of client and server. You may also need to wait for the subscription to Documents to complete before you can expect content. So safer is:
Meteor.subscribe('testData', function() {
var document = Documents.find();
console.log(document);
});

Resources