How to save the result in variable of findOne() Mongoose using nodejs - node.js

I am trying to save the result of findOne(), however, I do not have any idea how to save this result in a variable.
function createSubscription (req, res, next) {
let product_id = "P-5JM98005MT260873LLT44E2Y" ;
let doc = null;
product.findOne({"plans.id": product_id}, { "plans.$": 1
}).sort({create_time: -1}).exec(function(err, docs) {
if(err) {
} else {
if(docs != null) {
this.doc = docs;
}
}
});
console.log(doc);
let result = null;
if (doc.create != null) {
result = processDoc(doc);
}
}
function processDoc(doc) {
//do something
return resul;
}
function processResult(result) {
//do something
}
Below, I copy the product schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ProductSchema = new Schema({
id: {
type: String,
trim: true,
required: true,
},
name: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
create_time: {
type: Date,
required: true,
}
});
module.exports = mongoose.model('Product', ProductSchema);
The doc is always null and does not receive the value.
In general terms, I would like to get the response product.findOne to use another function, calling by createSubscription()

To save the result of findOne() is as easy as this:
var doc = product.findOne();
The problem you're having is that you are calling processDoc() before findOne() is finished. Look into asynchronous javascript. You can fix this by using async/await like this:
async function createSubscription (req, res, next) {
var doc = await product.findOne();
processDoc(doc);
}

The reason is you are calling a callback function, which means function is asynchronous. So there is no guarantee that your query will execute and the values will be set before it reaches to,
if (doc.create != null) {
result = processDoc(doc);
}
To resolve this you may use the Async/Await Syntax:
const createSubscription = async function (params) {
try { return await User.findOne(params)
} catch(err) { console.log(err) }
}
const doc = createSubscription({"plans.id": product_id})

Since you want to query something in database, that means you already created one and saved some data in it.
However before saving data in the database you should be creating your model which should be created under models folder in Product.js(model names should start capital letter in convention) . Then you have to IMPORT it in your above page to access it. You want to query by product.id but which product's id?
Since you have req in your function, that means you are posting something. If you set up the proper settings in app.js you should be able to access to req.body which is the information that being posted by the client side.
app.js //setting for parsing(reading or accessing) req.body
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
Now we can reach req.body.id
this should be your code:
function createSubscription (req, res, next) {
const product=Product.findOne({plan.id:req.body.id})
.
.
}
If you noticed I did not put this plan.id in quotes.Because findOne() method belongs the Product model and that model belongs to the package that you are using. (In mongoose you query without quotes, in mongodb client you query in quotes)
findOne() is an asynchronous operation means result will not come to you immediately. So you should always keep it in try/catch block.
function createSubscription (req, res, next) {
try{
const product=Product.findOne({plan.id:req.body.id})
}
catch(error){console.log(error.message)} //every error object has message property
.
.
}
Lastly since you are querying only one object you do not need to sort it.

Related

how to get the existing collection in mongodb using mongose- Nodejs

In my mongodb i already had a collection and document
Now, i want to use this collection in my node-js using mongoose. how we do this.
const mongoose = require("mongoose");
const schema = mongoose.Schema;
const adminLogin = new schema({
name: { type: String, required: true },
password: { type: String, required: true }
})
module.exports = mongoose.model("adminDetails", adminLogin)
while doing this it is creating new collection. Unable to use the existing collection.
At first you need to make a GET method Router in your jsFile.
like this
app.get("/mainData", async (req, res) => {
const menuInfo = await Nutrients.find({});
res.json(menuInfo);
});
You can set and use VSCode extension "thunderClient"!
like this
enter image description here
setting your request method and URI endpoint
(when you user GET method to get some data in your case, you don't need to write something in request body)
Then, you can see your data on the 'response part' as an Object Data.
If you want to use your data on Front side on your Project, you can use like this!
(in my case, I used jQuery. )
function menu_show() {
$('#result_list').empty()
$.ajax({
type: 'GET',
url: '/mainData', //you need to write same url with your no3.
data: {},
success: function (response) {
console.log(response)
let rows = response['menus']
for (let i = 0; i < rows.length; i++) {
let menuName = rows[i]['menuName']
console.log(menuName)
}
}
}
This is my answer. Let me know if you've solved it!
the image 1 is the structure in the MongoDB. I want to read the data from that collection, below is the code using and the URL and output in post man.
route.get('/adminLogin', (request, response) => {
const data = adminDetails.find({}, (err, result) => {
if (err) {
console.log(err)
} else {
res.json(result)
}
})
})
http://localhost:5000/admin/adminLogin

I define nested schema , when i fill the inputs it returns nothing and not save in Mongodb

I define nested schema but when I send input data returns nothing,
how can I solve this issue ?
this is my result:
{
"message": "handeling post request to /user-api",
"CreatedUserInfo": {
"_id": "5cbb7fbaad28fe209099a57c"
}
}
this is my code :
const userEduSchema = new mongoose.Schema(
{
eduLevel : String ,
eduField : String,
eduInst :String,
eduCity :String,
eduDate :Date,
proposalTitle :String
}
)
const allEduSchema = new mongoose.Schema(
{
bsc: userEduSchema,
master: userEduSchema,
phd: userEduSchema ,
}
)
module.exports = mongoose.model('Users', allEduSchema )
and it is my user.js for save inpute data in MongoDB I don't know this is true or not:
const userModels = require('../../models/userModels')
router.post('/', (req , res, next) => {
const user = new userModels({
_id : new mongoose.Types.ObjectId,
eduLevel :req.body.eduLevel,
eduField :req.body.eduField,
eduInst :req.body.eduInst,
eduCity :req.body.eduCity,
eduDate :req.body.eduDates,
proposalTitle :req.body.proposalTitle,
})
user.save().then(result =>{
console.log(result)
}).catch (err => {
console.log(err)
})
res.status(201).json ({
message:'handeling post request to /user-api',
CreatedUserInfo : user
})
})```
The problem was in defining the way of get the inputs,I must define the nested object and inside of that put the request bodies as well as I define the nested schema.
bsc:{
bscEduLevel :req.body.bscEduLevel,
bscEduField :req.body.bscEduField,
bscEduInst :req.body.bscEduInst,
bscEduCity :req.body.bscEduCity,
bscEduDate :req.body.bscEduDate,
bscProposalTitle :req.body.bscProposalTitle
}
Have you defined userSchema? If not, you are trying to export a schema which does not exist. Again, in case you have not defined userSchema and you want to export allEduSchema, replace the last line of your model file with this:
const EduSchema = mongoose.model("EduSchema", allEduSchema);
module.exports = EduSchema;
Before you create a new user ,you need to require your "User" moongose Schema. Just like dimitris tseggenes said.
I use async function and try/catch to handle this problem.Maybe you could....
router.post("/", async (request, response) => {
try {
const user = new Users({new user's data here..... });
const result = await user.save();
response.send(result);
} catch (error) {
response.status(400).send(error);
}
});
try catch could avoid some unexpected error and handle it.

find by _id with Mongoose

I am having trouble with a simple findById with mongoose.
Confirmed the item exists in the DB
db.getCollection('stories').find({_id:'572f16439c0d3ffe0bc084a4'})
With mongoose
Story.findById(topic.storyId, function(err, res) {
logger.info("res", res);
assert.isNotNull(res);
});
won't find it.
I also tried converting to a mongoId, still cannot be found (even though mongoose supposedly does this for you)
var mid = mongoose.Types.ObjectId(storyId);
let story = await Story.findOne({_id: mid}).exec();
I'm actually trying to use this with typescript, hence the await.
I also tried the Story.findById(id) method, still cannot be found.
Is there some gotcha to just finding items by a plain _id field?
does the _id have to be in the Schema? (docs say no)
I can find by other values in the Schema, just _id can't be used...
update: I wrote a short test for this.
describe("StoryConvert", function() {
it("should read a list of topics", async function test() {
let topics = await Topic.find({});
for (let i = 0; i < topics.length; i ++) {
let topic = topics[i];
// topics.forEach( async function(topic) {
let storyId = topic.storyId;
let mid = mongoose.Types.ObjectId(storyId);
let story = await Story.findOne({_id: mid});
// let story = await Story.findById(topic.storyId).exec();
// assert.equal(topic.storyId, story._id);
logger.info("storyId", storyId);
logger.info("mid", mid);
logger.info("story", story);
Story.findOne({_id: storyId}, function(err, res) {
if (err) {
logger.error(err);
} else {
logger.info("no error");
}
logger.info("res1", res);
});
Story.findOne({_id: mid}, function(err, res) {
logger.info("res2", res);
});
Story.findById(mid, function(err, res) {
logger.info("res3", res);
// assert.isNotNull(res);
});
}
});
});
It will return stuff like
Testing storyId 572f16439c0d3ffe0bc084a4
Testing mid 572f16439c0d3ffe0bc084a4
Testing story null
Testing no error
Testing res1 null
Testing res2 null
Testing res3 null
I noticed that topic.storyId is a string
not sure if that would cause any issues mapping to the other table.
I tried also adding some type defs
storyId: {
type: mongoose.Schema.Types.ObjectId,
required: false
}
Because this query finds the doc in the shell:
db.getCollection('stories').find({_id:'572f16439c0d3ffe0bc084a4'})
That means that the type of _id in the document is actually a string, not an ObjectId like Mongoose is expecting.
To find that doc using Mongoose, you'd have to define _id in the schema for Story as:
_id: { type: String }
If your Mongo schema is configured to use Object Id, you query in nodeJS using
models.Foo.findById(id)
where Foo is your model and id is your id.
here's a working example
router.get('/:id', function(req, res, next) {
var id = req.params.id
models.Foo.findById(id)
.lean().exec(function (err, results) {
if (err) return console.error(err)
try {
console.log(results)
} catch (error) {
console.log("errror getting results")
console.log(error)
}
})
})
In Mongo DB your query would be
{_id:ObjectId('5c09fb04ff03a672a26fb23a')}
One solution is to use mongoose.ObjectId()
const Model = require('./model')
const mongoose = require('mongoose')
Model.find({ id: mongoose.ObjectId(userID) })
It works, but it is weird because we are using id instead of _id
This is how we do it now:
const { mongoose } = require("mongoose");
YourModel.find({ _id: mongoose.Types.ObjectId("572f16439c0d3ffe0bc084a4") });
I got into this scenario too. This was how I solved it;
According to the mongoose documentation, you need to tell mongoose to
return the raw js objects, not mongoose documents by passing the lean option and setting it to true. e.g
Adventure.findById(id, 'name', { lean: true }, function (err, doc) {});
in your situation, it would be
Story.findById(topic.storyId, { lean: true }, function(err, res) {
logger.info("res", res);
assert.isNotNull(res);
});
If _id is the default mongodb key, in your model set the type of _id as this:
_id: mongoose.SchemaTypes.ObjectId
Then usind mongoose you can use a normal find:
YourModel.find({"_id": "5f9a86b77676e180c3089c3d"});
models.findById(id)
TRY THIS ONE .
REF LINK : https://www.geeksforgeeks.org/mongoose-findbyid-function/
Try this
Story.findOne({_id:"572b19509dac77951ab91a0b"}, function(err, story){
if (err){
console.log("errr",err);
//return done(err, null);
}else{
console.log(story);
}
});

How to organize code / logic with node.js / Express 3, and Mongoose (MongoDB)

I see lots of examples where node.js / express router code is organized like this:
// server.js
var cats = require('cats');
app.get('/cats', cats.findAll);
// routes/cats.js
exports.findAll = function(req, res) {
// Lookup all the cats in Mongoose CatModel.
};
I'm curious if it would be okay to put the logic to create, read, update and delete cats in the mongoose CatModel as methods? So you could do something like cat.findAll(); The model might look something like this:
var Cat = new Schema({
name: {
type: String,
required: true
}
});
Cat.methods.findAll = function(callback) {
// find all cats.
callback(results);
}
Then you could use this in your router:
app.get('/cats', cats.findAll);
If if further logic / abstraction is needed (to process the results) then one could do it in routes/cats.js.
Thanks in Advance.
Obviously your architecture is completely up to you. I've found that separating my routes (which handle business logic) and models (which interact with the db) is necessary and very easy.
So I would usually have something like
app.js
var cats = require ('./routes/cats');
app.get('/api/cats', cats.getCats);
routes/cats.js
var Cats = require ('../lib/Cats');
exports.getCats = function (req, res, next) {
Cat.get (req.query, function (err, cats) {
if (err) return next (err);
return res.send ({
status: "200",
responseType: "array",
response: cats
});
});
};
lib/Cat.js
var catSchema = new Schema({
name: {
type: String,
required: true
}
});
var Cat = mongoose.model ('Cat', catSchema);
module.exports = Cat;
Cat.get = function (params, cb) {
var query = Cat.find (params);
query.exec (function (err, cats) {
if (err) return cb (err);
cb (undefined, cats);
});
};
So this example doesn't exactly show an advantage, but if you had an addCat route, then the route could use a "getCatById" function call, verify the cat doesn't exist, and add it. It also helps with some nesting. The routes could also be used for sanitizing the objects before sending them off, and might also send resources and information used in UI that isn't necessarily coupled with mongoose. It also allows interactions with the database to be reusable in multiple routes.

NodeJS + MongoDB: Getting data from collection with findOne ()

I have a collection "companies" with several objects. Every object has "_id" parameter. I'm trying to get this parameter from db:
app.get('/companies/:id',function(req,res){
db.collection("companies",function(err,collection){
console.log(req.params.id);
collection.findOne({_id: req.params.id},function(err, doc) {
if (doc){
console.log(doc._id);
} else {
console.log('no data for this company');
}
});
});
});
So, I request companies/4fcfd7f246e1464d05000001 (4fcfd7f246e1464d05000001 is _id-parma of a object I need) and findOne returns nothing, that' why console.log('no data for this company'); executes.
I'm absolutely sure that I have an object with _id="4fcfd7f246e1464d05000001". What I'm doing wrong? Thanks!
However, I've just noticed that id is not a typical string field. That's what mViewer shows:
"_id": {
"$oid": "4fcfd7f246e1464d05000001"
},
Seems to be strange a bit...
You need to construct the ObjectID and not pass it in as a string. Something like this should work:
var BSON = require('mongodb').BSONPure;
var obj_id = BSON.ObjectID.createFromHexString("4fcfd7f246e1464d05000001");
Then, try using that in your find/findOne.
Edit: As pointed out by Ohad in the comments (thanks Ohad!), you can also use:
new require('mongodb').ObjectID(req.params.id)
Instead of createFromHexString as outlined above.
That's because _id field in mongo isn't of string type (as your req.params.id). As suggested in other answers, you should explicitly convert it.
Try mongoskin, you could use it like node-mongodb-native driver, but with some sugar. For example:
// connect easier
var db = require('mongoskin').mongo.db('localhost:27017/testdb?auto_reconnect');
// collections
var companies = db.collection('companies');
// create object IDs
var oid = db.companies.id(req.params.id);
// some nice functions…
companies.findById();
//… and bindings
db.bind('companies', {
top10: function(callback) {
this.find({}, {limit: 10, sort: [['rating', -1]]).toArray(callback);
}
});
db.companies.top10(printTop10);
You can use findById() which will take care of the id conversion for you.
company = Company.findById(req.params.id, function(err, company) {
//////////
});
In case these didn't work for you, this worked for me for accessing a blog post:
const getSinglePost = async (req, res) => {
let id = req.params.id;
var ObjectId = require('mongodb').ObjectId;
const db = await client.db('CMS');
const data = await db.collection("posts").findOne({ _id: ObjectId(id) })
if (data) {
res.status(200).send(data)
} else res.status(400).send({ message: "no post found" })
}

Resources