Mongoose find returns empty array (works fine for other collections) - node.js

I have been writing a restful api in nodejs fairly succesfully for the most part. There are two collections in the MongoDB that I am accessing that return empty strings and happen to be the only collections that contain capital letters in their names. When I use MongoClient, I am able to access these collections just fine, so I know that it is not an out of date mongodb driver.
one example is when I try to access a collection called bulkBuds
//bulkBuds model
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var BulkBudsSchema = new Schema({
sourceLicense: String,
quantity: Number,
strainName: String,
priceProfile: String
});
mongoose.model('bulkBuds', BulkBudsSchema);
The controller has a bit of excess logic in the query, but a simple find returns an empty string as well.
//bulkBuds controller
var express = require('express'),
router = express.Router(),
mongoose = require('mongoose'),
BulkBuds = mongoose.model('bulkBuds'),
Friends = mongoose.model('Api'),
config = require('../../config/config'),
jwt = require('express-jwt');
module.exports = function (app) {
app.use('/api/bulkBuds/', router);
};
router.get('/:license', jwt({secret: config.secret}), function (req, res, next) {
if(!req.user.friend){
res.status(401);
}
Friends.findById(req.user.id, function(err, friend){
if(err) throw err;
if(!friend) res.send("friend does not exist");
if(req.user.username != friend.username) res.send("invalid user");
console.log(req.params.license);
console.log(BulkBuds.find({}));
BulkBuds.find({'storeLicense': req.params.license, 'availableForSale': true},
"sourceLicense quantity strainName priceProfile", function (err, bulkBuds) {
if (err) return next(err);
console.log(bulkBuds);
res.send(bulkBuds);
});
})
});
Any suggestions would be greatly appreciated, thanks.

Very difficult to answer without being able to test against your database. But I would try a few things.
refactor {'storeLicense': req.params.license, 'availableForSale': true} to create the object outside of the query, and then console log that object prior to passing it to the query. That will ensure everything is as you expect.
Remove "sourceLicense quantity strainName priceProfile" as the second argument to BulkBuds.find, and replace with an empty object. I usually pass an object as the second param with the following syntax {_id:1,quantity:0} to modify the projection. Your syntax may work, but just in case I would try running the query without to see if that yields any results.
Confirm quantity in your db is indeed a Number and not a String. I know mongoose won't let you insert records that don't validate, not sure about querying. Most likely not the issue, but doesn't hurt to verify.
After creating the Bulkbirds schema try this:
mongoose.model('bulkBuds', BulkBudsSchema, 'bulkBuds');
Another long shot, but perhaps it has something to do with mongoose pluralizing the collection names. Using the above syntax will ensure it's querying the bulkBuds collection.
Once again, difficult to pinpoint without being able to test, but hopefully those ideas help.

Related

.find() returns empty when used with node.js and mongoose but returns data on mongo shell [duplicate]

I have tried using find and findOne and both are not returning a document. find is returning an empty array while findOne is returning null. err in both cases in null as well.
Here is my connection:
function connectToDB(){
mongoose.connect("mongodb://localhost/test"); //i have also tried 127.0.0.1
db = mongoose.connection;
db.on("error", console.error.bind(console, "connection error:"));
db.once("open", function callback(){
console.log("CONNECTED");
});
};
Here is my schema:
var fileSchema = mongoose.Schema({
hash: String,
type: String,
extension: String,
size: String,
uploaded: {type:Date, default:(Date.now)},
expires: {type:Date, default:(Date.now()+oneDay)}
});
var Model = mongoose.model("Model", fileSchema);
And my query is here:
Model.find({},function(err, file) {
console.log(err)
console.log(file);
});
I can upload things to the database and see them via RockMongo but I cannot fetch them after. This my first time using MongoDB so I think I'm just missing some of the fundamentals. Any push in the right direction would be great!
The call to mongoose.model establishes the name of the collection the model is tied to, with the default being the pluralized, lower-cased model name. So with your code, that would be 'models'. To use the model with the files collection, change that line to:
var Model = mongoose.model("Model", fileSchema, "files");
or
var Model = mongoose.model("file", fileSchema);
Simply inorder to avoid pluralization complexity use this:
var Model = mongoose.model("Model", fileSchema, "pure name your db collection");
It's very confusing.[at least for me.]
Had kinda same problem. The solutions above didnt work for me. My app never returns error even if the query is not found. It returns empty array. So i put this in my code:
if(queryResult.length==0) return res.status(404).send("not found");
This issue is probably coming from the fact that you are creating a mongoose model without specifying the name of the collection.
Try changing : const Model = mongoose.model("Model", fileSchema);
To this : const Model = mongoose.model("Model", fileSchema, "NameOfCollection");
const growingUnit= mongoose.model('Growing Unit', growingUnitSchema);
I had a space in 'Growing Unit' on purpose and it always returned empty array. Removing that space to become 'GrowingUnit' was the fix needed in my scenario.
const growingUnit= mongoose.model('Growing Unit', growingUnitSchema);
General "hello world" issues (Sometimes this issue not related to mongoose).
Check if the collection is not really empty (mongoDB atlas screenshot).
Check for small spelling differences (Like listing instead of listings) in your collection queries commands.
Check if you use the correct URI for your connection (For example you are trying to retrieve data from a collection that exists in localhost but use mongoDB cluster (Cloud) -or- any other issue related to Connection String URI).
https://docs.mongodb.com/manual/reference/connection-string/
For me the issue was .skip(value), I was passing page=1 instead of page=0.
As I was having few records, I was getting empty array always.

Cannot fetch data from MongoDB using Mongoose [duplicate]

I have tried using find and findOne and both are not returning a document. find is returning an empty array while findOne is returning null. err in both cases in null as well.
Here is my connection:
function connectToDB(){
mongoose.connect("mongodb://localhost/test"); //i have also tried 127.0.0.1
db = mongoose.connection;
db.on("error", console.error.bind(console, "connection error:"));
db.once("open", function callback(){
console.log("CONNECTED");
});
};
Here is my schema:
var fileSchema = mongoose.Schema({
hash: String,
type: String,
extension: String,
size: String,
uploaded: {type:Date, default:(Date.now)},
expires: {type:Date, default:(Date.now()+oneDay)}
});
var Model = mongoose.model("Model", fileSchema);
And my query is here:
Model.find({},function(err, file) {
console.log(err)
console.log(file);
});
I can upload things to the database and see them via RockMongo but I cannot fetch them after. This my first time using MongoDB so I think I'm just missing some of the fundamentals. Any push in the right direction would be great!
The call to mongoose.model establishes the name of the collection the model is tied to, with the default being the pluralized, lower-cased model name. So with your code, that would be 'models'. To use the model with the files collection, change that line to:
var Model = mongoose.model("Model", fileSchema, "files");
or
var Model = mongoose.model("file", fileSchema);
Simply inorder to avoid pluralization complexity use this:
var Model = mongoose.model("Model", fileSchema, "pure name your db collection");
It's very confusing.[at least for me.]
Had kinda same problem. The solutions above didnt work for me. My app never returns error even if the query is not found. It returns empty array. So i put this in my code:
if(queryResult.length==0) return res.status(404).send("not found");
This issue is probably coming from the fact that you are creating a mongoose model without specifying the name of the collection.
Try changing : const Model = mongoose.model("Model", fileSchema);
To this : const Model = mongoose.model("Model", fileSchema, "NameOfCollection");
const growingUnit= mongoose.model('Growing Unit', growingUnitSchema);
I had a space in 'Growing Unit' on purpose and it always returned empty array. Removing that space to become 'GrowingUnit' was the fix needed in my scenario.
const growingUnit= mongoose.model('Growing Unit', growingUnitSchema);
General "hello world" issues (Sometimes this issue not related to mongoose).
Check if the collection is not really empty (mongoDB atlas screenshot).
Check for small spelling differences (Like listing instead of listings) in your collection queries commands.
Check if you use the correct URI for your connection (For example you are trying to retrieve data from a collection that exists in localhost but use mongoDB cluster (Cloud) -or- any other issue related to Connection String URI).
https://docs.mongodb.com/manual/reference/connection-string/
For me the issue was .skip(value), I was passing page=1 instead of page=0.
As I was having few records, I was getting empty array always.

Mongoose some field are not inserted [duplicate]

In previous versions of Mongoose (for node.js) there was an option to use it without defining a schema
var collection = mongoose.noSchema(db, "User");
But in the current version the "noSchema" function has been removed. My schemas are likely to change often and really don't fit in with a defined schema so is there a new way to use schema-less models in mongoose?
I think this is what are you looking for Mongoose Strict
option: strict
The strict option, (enabled by default), ensures that values added to our model instance that were not specified in our schema do not get saved to the db.
Note: Do not set to false unless you have good reason.
var thingSchema = new Schema({..}, { strict: false });
var Thing = mongoose.model('Thing', thingSchema);
var thing = new Thing({ iAmNotInTheSchema: true });
thing.save() // iAmNotInTheSchema is now saved to the db!!
Actually "Mixed" (Schema.Types.Mixed) mode appears to do exactly that in Mongoose...
it accepts a schema-less, freeform JS object - so whatever you can throw at it. It seems you have to trigger saves on that object manually afterwards, but it seems like a fair tradeoff.
Mixed
An "anything goes" SchemaType, its flexibility comes at a trade-off of
it being harder to maintain. Mixed is available either through
Schema.Types.Mixed or by passing an empty object literal. The
following are equivalent:
var Any = new Schema({ any: {} });
var Any = new Schema({ any: Schema.Types.Mixed });
Since it is a schema-less type, you can change the value to anything
else you like, but Mongoose loses the ability to auto detect and save
those changes. To "tell" Mongoose that the value of a Mixed type has
changed, call the .markModified(path) method of the document passing
the path to the Mixed type you just changed.
person.anything = { x: [3, 4, { y: "changed" }] };
person.markModified('anything');
person.save(); // anything will now get saved
Mongoose Schema Types
Hey Chris, take a look at Mongous. I was having the same issue with mongoose, as my Schemas change extremely frequently right now in development. Mongous allowed me to have the simplicity of Mongoose, while being able to loosely define and change my 'schemas'. I chose to simply build out standard JavaScript objects and store them in the database like so
function User(user){
this.name = user.name
, this.age = user.age
}
app.post('save/user', function(req,res,next){
var u = new User(req.body)
db('mydb.users').save(u)
res.send(200)
// that's it! You've saved a user
});
Far more simple than Mongoose, although I do believe you miss out on some cool middleware stuff like "pre". I didn't need any of that though. Hope this helps!!!
Here is the details description: [https://www.meanstack.site/2020/01/save-data-to-mongodb-without-defining.html][1]
const express = require('express')()
const mongoose = require('mongoose')
const bodyParser = require('body-parser')
const Schema = mongoose.Schema
express.post('/', async (req, res) => {
// strict false will allow you to save document which is coming from the req.body
const testCollectionSchema = new Schema({}, { strict: false })
const TestCollection = mongoose.model('test_collection', testCollectionSchema)
let body = req.body
const testCollectionData = new TestCollection(body)
await testCollectionData.save()
return res.send({
"msg": "Data Saved Successfully"
})
})
[1]: https://www.meanstack.site/2020/01/save-data-to-mongodb-without-defining.html
Note: The { strict: false } parameter will work for both create and update.
Its not possible anymore.
You can use Mongoose with the collections that have schema and the node driver or another mongo module for those schemaless ones.
https://groups.google.com/forum/#!msg/mongoose-orm/Bj9KTjI0NAQ/qSojYmoDwDYJ

Node.js, Express.js and MongoDB - Security about user input with find and insert

I created a set of REST services based on Express.js to find some results stored in a Mongo Database. A very minimal version of the code for one of the services could be something like:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var mongoClient = require('mongodb').MongoClient;
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.get('/results/:name', function(req, res){
var name = req.params.name;
mongoClient.connect('mongodb://localhost/test', function (err, db) {
var collection = db.collection('results');
collection.find({ name: name }).toArray( function (err, docs) {
res.json({results: docs});
});
});
});
app.listen(3000);
I'm coming from Java and I've been beaten by SQL injections in the past. So I'm not at all comfortable with using the user's input directly in the find request. With my very thin knowledge of the subject, I tried several special characters ( } ) " ' ; and so on) but I've not been able to produce any weird result.
What could go wrong here? What kind of validations or checks should I implement to make sure that it is not possible to inject code or to make the program fail?
Now, let's do something stupid and let's trust the user to input a correct record:
app.post('/results/', function(req, res){
var record = req.body;
if( record.name ) {
mongoClient.connect('mongodb://localhost/test', function (err, db) {
var collection = db.collection('results');
collection.insert( record, function(err, doc){});
res.json({message: 'ok'});
});
}
});
How can I validate the schema of the input? And apart from filling the DB with thousand of gigantic inputs, is it possible to exploit this code to inject some code? If yes, how to prevent that?
Thanks a lot!
I would have put this as a comment but since I'm not yet allowed to do that i'll just put it as a responce.
I go into the details since I'm not the expert here but here is an article I've found to be really interresting about vulnerability when using mongo and node.js.
For validating the model, I use mongoose as a client to my mongoDB, it helps a lot as it has its own validators and you can as well make your own.
I hope it helps you into your search.
Mongodb access is api-based, as oposed to SQL that is language-based. SQL is a language, and if you let inputs from users to be inserted in the language, then it is easy to make code injection and do almost everything to your database.
MongoDB has a different approach, when you are doing a search, you call an API function to do the search, and this API function can only do searchs.
If you let the user choose the fields and the values, then he can make searchs that you don't expect, but that's all.
The same applies for inserts, updates and deletes, be careful of not letting the user to choose the fields and the values, because he can choose ones that you do not expects nor wants.

Mongoose always returning an empty array NodeJS

I have tried using find and findOne and both are not returning a document. find is returning an empty array while findOne is returning null. err in both cases in null as well.
Here is my connection:
function connectToDB(){
mongoose.connect("mongodb://localhost/test"); //i have also tried 127.0.0.1
db = mongoose.connection;
db.on("error", console.error.bind(console, "connection error:"));
db.once("open", function callback(){
console.log("CONNECTED");
});
};
Here is my schema:
var fileSchema = mongoose.Schema({
hash: String,
type: String,
extension: String,
size: String,
uploaded: {type:Date, default:(Date.now)},
expires: {type:Date, default:(Date.now()+oneDay)}
});
var Model = mongoose.model("Model", fileSchema);
And my query is here:
Model.find({},function(err, file) {
console.log(err)
console.log(file);
});
I can upload things to the database and see them via RockMongo but I cannot fetch them after. This my first time using MongoDB so I think I'm just missing some of the fundamentals. Any push in the right direction would be great!
The call to mongoose.model establishes the name of the collection the model is tied to, with the default being the pluralized, lower-cased model name. So with your code, that would be 'models'. To use the model with the files collection, change that line to:
var Model = mongoose.model("Model", fileSchema, "files");
or
var Model = mongoose.model("file", fileSchema);
Simply inorder to avoid pluralization complexity use this:
var Model = mongoose.model("Model", fileSchema, "pure name your db collection");
It's very confusing.[at least for me.]
Had kinda same problem. The solutions above didnt work for me. My app never returns error even if the query is not found. It returns empty array. So i put this in my code:
if(queryResult.length==0) return res.status(404).send("not found");
This issue is probably coming from the fact that you are creating a mongoose model without specifying the name of the collection.
Try changing : const Model = mongoose.model("Model", fileSchema);
To this : const Model = mongoose.model("Model", fileSchema, "NameOfCollection");
const growingUnit= mongoose.model('Growing Unit', growingUnitSchema);
I had a space in 'Growing Unit' on purpose and it always returned empty array. Removing that space to become 'GrowingUnit' was the fix needed in my scenario.
const growingUnit= mongoose.model('Growing Unit', growingUnitSchema);
General "hello world" issues (Sometimes this issue not related to mongoose).
Check if the collection is not really empty (mongoDB atlas screenshot).
Check for small spelling differences (Like listing instead of listings) in your collection queries commands.
Check if you use the correct URI for your connection (For example you are trying to retrieve data from a collection that exists in localhost but use mongoDB cluster (Cloud) -or- any other issue related to Connection String URI).
https://docs.mongodb.com/manual/reference/connection-string/
For me the issue was .skip(value), I was passing page=1 instead of page=0.
As I was having few records, I was getting empty array always.

Resources