MongoDb query by _id using Node - node.js

const cCurser = await client
.db("Database")
.collection("Collection")
.findOne({
_id: ObjectId(Filter)
}).then(function(item){
Obj = item;}
);
I'm trying to query the MongoDB by the _id but it returns Promise { }. please help me to retrieve the data in it.
Error detected:ReferenceError: ObjectId is not defined

add this before your query:
import mongoose from 'mongoose';
const { ObjectId } = mongoose.Types;
OR:
use this:
const cCurser = await client
.db("Database")
.collection("Collection")
.findOne({
_id: new mongoose.Types.ObjectId(Filter)
}).then(function(item){
Obj = item;}
);

Firstly, don't mix await syntax with the then syntax.
Either use await
let Obj = null;
const cCurser = await client
.db("Database")
.collection("Collection")
.findOne({
_id: ObjectId(Filter)
});
//Use Obj
Or the then syntax. Here you will have to write the rest of the code dependent on Obj inside then().
let Obj = null;
const cCurser = client
.db("Database")
.collection("Collection")
.findOne({
_id: ObjectId(Filter)
}).then(function(item){
Obj = item;
//Use Obj
}
);
Also based on your edit,it seems you have not imported ObjectId method from Mongo.
let mongo = require('mongodb');
let ObjectId = mongo .ObjectID
```

Related

how to check number of documents insert in MongoDB with Mongoose in console.log

I just begin to learn how to use MongoDB and Mongoose, So I try to insert some docs in MongoDB running locally, this is how i do it when I use only MongoDB driver :
const { MongoClient } = require("mongodb");
const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);
async function run() {
const dbName = client.db("fruitsDB");
try {
await client.connect();
// I insert the function to insert the docs here
await insertMultiDocs(dbName, docs);
// Establish and verify connection
await client.db("admin").command({ ping: 1 });
console.log("Connected successfully to server");
} finally {
await client.close();
}
}
run().catch(console.dir);
// below is the docs I want to insert and the function I use like the MongoDB's
// documentation.
const docs = [
{ name: "Ananas", rating: 7, review: "nice fruit"},
{ name: "Prune", rating: 8, review: "Kinda good"},
{ name: "Peach", rating: 7, review: "taste great"},
{ name: "Strawberry", rating: 9, review: "great fruit"}
];
async function insertMultiDocs (client, newList) {
try {
const insertManyresult = await client.collection("fruits").insertMany(newList);
let ids = insertManyresult.insertedIds;
console.log(`${insertManyresult.insertedCount} documents were inserted.`);
for (let id of Object.values(ids)) {
console.log(`Inserted a document with id ${id}`);
}
} catch(e) {
console.log(`A MongoBulkWriteException occurred, but there are successfully processed documents.`);
let ids = e.result.result.insertedIds;
for (let id of Object.values(ids)) {
console.log(`Processed a document with id ${id._id}`);
}
console.log(`Number of documents inserted: ${e.result.result.nInserted}`);
}
}
Then I get this console.log :
4 documents were inserted.
Inserted a document with id 63051aeb6b883a87e46ea895
Inserted a document with id 63051aeb6b883a87e46ea896
Inserted a document with id 63051aeb6b883a87e46ea897
Inserted a document with id 63051aeb6b883a87e46ea898
Connected successfully to server
Now I want to try to do the same with Mongoose :
const mongoose = require("mongoose");
const { Schema } = mongoose;
main().catch(err => console.log(err));
async function main() {
try {
await mongoose.connect("mongodb://localhost:27017/fruitsDB");
const fruitSchema = new Schema({
name : String,
rating : Number,
review : String
});
const Fruit = mongoose.model("Fruit", fruitSchema);
// I insert the docs here...
Fruit.insertMany(docs)
} catch (error) {
console.log(error);
}
}
It work, however is there a way to implemente the console.log in Mongoose and loop through each document inserted like the way it did on MongoDB drive ?
insertMany returns the documents that are added to DB post the validation (if any validations are set in place).
You can just .length on it to get the value like this
const insertManyresult = await Fruit.insertMany(docs);
console.log(`${insertManyresult.length} documents were inserted.`);
Since you have access to all the documents. You can perform any operation of choice (loop over every document, get length etc.)
Read more about insertMany here.

Firebase where query

I have a problem, here is the code:
const firstName = "rick";
const users = await db.collection('user');
if (firstName != undefined) {
users.where("name", "==", firstName );
}
const snap = users.get();
why this query return me the whole document with all objects? How to do a query based on where clause that can be null or undefined? Thanks for any help!
You are not reassigning the users and hence it's fetching whole collection. Try refactoring like this:
let users: firebase.firestore.Query = db.collection('user');
//^ let instead of const
if (firstName) {
users = users.where("name", "==", firstName );
// ^^ updating original 'users' value
}
const snap = users.get();

Mongoose query doesn't work with the filter

I'm testing a nodejs snippet to do iteration with my example mongodb collection users. But the query never worked. The full users collection are printed.
The standalone mongodb is setup in EKS cluster.
Why the query {name: "Baker one"} didn't work?
The code is:
const mongoose = require("mongoose");
const url = "mongodb://xxxxxx:27017/demo";
main().catch(error => console.error(error.stack));
async function main() {
// Connect to DB
const db = await mongoose.connect(url);
console.log("Database connected!");
const { Schema } = mongoose;
// Init Model
const Users = mongoose.model("Users", {}, "users");
const users = await Users.find({name: "Baker one"}).exec();
// Iterate
for await (const doc of users) {
console.log(doc);
console.log("users...");
}
console.log("about to close...");
db.disconnect();
}
The users collection:
The execution result:
$ node modify.js
Database connected!
{ _id: new ObjectId("610f512c52fa99dcd04aa743"), name: 'Baker one' }
users...
{ _id: new ObjectId("61193ed9b8af50d530576af6"), name: 'Bill S' }
users...
about to close...
This line could be the culprit (note that the schema has been defined with no fields like Joe pointed out in the comments).
const Users = mongoose.model("Users", {}, "users");
In this case, I had to add StrictQuery option in the Schema constructor to make it work, like so:
const userSchema = new Schema({}, { collection: "Users", strictQuery : false });

Why my mongoose schema add an array on top of my current array?

I'm querying a mongo document to retrieve the array info. The thing is my array is inside another array. I don't know how this happened. I'm force to map twice every time to get inside. Anyone knows why?
Here's the mongoose schema:
const mongoose = require("mongoose");
const mongo = require("mongodb");
const insertedLaw = require("./civilcode_section2_21.json");
const Law = mongoose.model(
"Laws",
new mongoose.Schema({
law_name: String,
section_name: String,
section_text: [String],
}),
);
// Law.insertMany(insertedLaw); (commented out because using Nodemon)
exports.Law = Law;
Here's my node route:
const express = require("express");
const {
Law,
} = require("../models/law");
const router = express.Router();
router.get("/", async (req, res) => {
const laws = await Law.find();
res.send(laws);
});
module.exports = router;
Here's my Jsx:
const urlLaw = "http://localhost:3000/api/laws";
class Dashboard extends Component {
state = {
laws: {},
sectionText: [],
};
async componentDidMount() {
await this.getLaws();
}
getLaws = async () => {
try {
const { data: laws } = await http.get(urlLaw);
const sectionText = laws.map((law) => law.section_text);
this.setState({ laws, sectionText });
console.log("You data has been received!");
} catch (ex) {
if (ex.response && ex.response === 404) alert("error receiving data");
}
};
Here's the result in console:
console.log
Here's my Mongo Document:
mongodoc
I can fetch the data but I feel it will become very clunky as I add more query. Thanks
I'm assuming your console.log image shows the result of await http.get(urlLaw).
You get nested arrays because in MongoDB and mongoose, "find" returns an array of documents. If you had more than one Law in your Laws collection, it would be clearer since you would see that this second document is returned too.
To sum up, the "outer" array is the array of the documents found by MongoDB and the "inner" array is the section_text field you want.
Use findOne if you want a document to be returned instead of an array of documents.

Using mongoose and Q.spread gives array callback parameters

I have the code below:
var mongoose = require('mongoose');
var Q = require("q")
mongoose.connect("mongodb://localhost/testdb");
var Schema = mongoose.Schema;
var employeeSchema = new Schema({
name:String
})
var Employee = mongoose.model('Employee', employeeSchema);
var departmentSchema = new Schema({
name:String
})
var Department = mongoose.model('Department', departmentSchema);
var employee = new Employee();
employee.name = "T.Smith";
var dept = new Department();
dept.name = "Sales";
Q.spread([
Q.nfcall(employee.save.bind(employee)),
Q.nfcall(dept.save.bind(dept))
],function(emp,dept){
console.log(JSON.stringify(emp));
console.log(JSON.stringify(dept));
mongoose.disconnect();
})
The log statements will yield the results below:
[{"__v":0,"name":"T.Smith","_id":"5358f3c53cd354bc70fe619f"},1]
[{"__v":0,"name":"Sales","_id":"5358f3c53cd354bc70fe61a0"},1]
Why are the results an array instead of a single object?
I get the same if i replace the last block of code with this block:
Q.all([
Q.nfcall(employee.save.bind(employee)),
Q.nfcall(dept.save.bind(dept))
]).spread(function(emp,dept){
console.log(JSON.stringify(emp));
console.log(JSON.stringify(dept));
mongoose.disconnect();
})
By the way, which block is recommended?
The save callback signature is function(err, result, numberAffected) which doesn't conform to node callback convention. nfcall expects a node callback signature, which is function(err, result). To avoid loss of information, the promise returned by nfcall resolves to [result, numberAffected].
Using .bind and Q.nfcall at call sites is very ugly anyway, so you can create a method that does all this:
mongoose.Model.prototype.saveForResult = function() {
return Q.nbind(this.save, this)().spread(function(result, numberAffected) {
return result;
});
};
Then:
Q.spread([
employee.saveForResult(),
dept.saveForResult()
],function(emp,dept){
console.log(JSON.stringify(emp));
console.log(JSON.stringify(dept));
mongoose.disconnect();
})

Resources