Geting empty array when find with some criteria in mongoose - node.js

Schema :
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Config = require('../Config');
var serviceAvailability = new Schema({
agentId: {type: Schema.ObjectId, ref: 'agentProfile', required: true},
availabilityDate: {type: Date, required: true},
availabilityTime: {type: Array, required: true}
});
serviceAvailability.index({agentId:1 , availabilityDate:1},{unique:true});
module.exports = mongoose.model('serviceAvailability', serviceAvailability);
Controller :
Models.serviceAvailability.find({'agentId':'abcd'}, function (err, service) {
console.log(service);
if(service) {
callback(err , service);
}
else {
callback(err);
}
});
I am trying to get all data with some criteria like if agentId is equal to some value but whenever i am using any criteria to find data i am getting empty array while if i remove the criteria and find all data then i am getting data, why is this ?

I think, you try to find a mongoDB document with a request on ObjectId Field, but, in your example, you don't use a correct ObjectId String Value.
ObjectId is a 12-byte BSON type, constructed using:
So, this is a correct way to request your serviceAbility with a correct ObjectId :
Models.serviceAvailability.find({
'agentId':'507f1f77bcf86cd799439011'
}, function (err, service) {
if (err) {
callback(err);
return;
}
callback(null, service);
});
In this case, you should have an agentProfile with the _id equals to 507f1f77bcf86cd799439011

Related

Store value of a subquery - mongoose

What im doing:
When I call getData() the backend server .find() all my data.
My documents:
My test document has an _id a name and stuff fields. The stuff field contains the _id to the data document.
My data document has an _id and a age field
My goal:
When I send the data to the frontend I donĀ“t want the stuff field to appear with the _id, I want it to appear with the age field from the correspondingdata.
What I have:
router.route('/data').get((req, res) => {
Test.find((err, aval) => {
if (err)
console.log(err);
else{
var result = [];
aval.forEach(e => {
var age;
// Get the age, only 1
Data.findById(e.stuff, 'age', function (err, a) {
age = a.age;
});
result.push({name: e.name, age: age});
});
res.json(result);
}
});
});
I find all the test documents then, for each one of them, I find the age and put the result in the array. Finaly I send the result array.
My problem:
The age field on my result array is always undefined, why? Any solutions?
UPDATE 1 - The schemas
The test schema
var TestSchema = new Schema(
{
stuff: {type: Schema.Types.ObjectId, ref: 'Data', required: true},
name: {type: String, required: true}
}
);
The data schema
var DataSchema = new Schema(
{
age: {type: Number, required: true}
}
);
router.route('/data').get((req, res) => {
Test.find({})
.populate('stuff')
.exec((err, aval) => {
if (err) console.log(err);
res.json(aval);
});
});
Mongoose model has a populate property that uses the value in the model attribute definition to get data matching the _id from another model.
It's a scop problem with your code try this out :
Data.findById(e.stuff, 'age', function (err, a) {
result.push({name: e.name, age: a.age});
});
But as a better solution think to use the Aggregation Framework

Autoincrement with Mongoose

I'm trying to implement an autoicremental user_key field. Looking on this site I came across two questions relevant for my problem but I don't clearly understand what I should do. This is the main one
I have two Mongoose models, this is my ProductsCounterModel.js
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var Counter = new Schema({
_id: {type: String, required: true},
sequence_value: {type: Number, default: 0}
});
module.exports = mongoose.model('products_counter', Counter);
and this is the Mongoose model where I try to implement the auto-increment field:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var products_counter = require('./ProductsCounterModel.js');
var HistoricalProduct = new Schema({
product_key: { type: Number },
class: { type: String },
brand: { type: String },
model: { type: String },
description: { type: String }
});
HistoricalProduct.pre("save", function (next) {
console.log("first console log:",products_counter);
var doc = this;
products_counter.findOneAndUpdate(
{ "_id": "product_key" },
{ "$inc": { "sequence_value": 1 } },
function(error, products_counter) {
if(error) return next(error);
console.log("second console log",products_counter);
doc.product_key = products_counter.sequence_value;
next();
});
});
module.exports = mongoose.model('HistoricalProduct', HistoricalProduct);
Following the steps provided in the above SO answer I created the collection products_counter and inserted one document.
The thing is that I'm getting this error when I try to insert a new product:
"TypeError: Cannot read property 'sequence_value' of null"
This are the outputs of the above console logs.
first console log output:
function model (doc, fields, skipId) {
if (!(this instanceof model))
return new model(doc, fields, skipId);
Model.call(this, doc, fields, skipId);
}
second console log:
Null
can you see what I'm doing wrong?
You can run following line in your middleware:
console.log(products_counter.collection.collectionName);
that line will print products_counters while you expect that your code will hit products_counter. According to the docs:
Mongoose by default produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Set this option if you need a different name for your collection.
So you should either rename collection products_counter to products_counters or explicitly configure collection name in your schema definition:
var Counter = new Schema({
_id: {type: String, required: true},
sequence_value: {type: Number, default: 0}
}, { collection: "products_counter" });

$match _id is not working in Mongoose aggregate function

As my title, $match _id is not working in Mongoose aggregate function.
Could somebody please help me?
Is this related to mongoose version?
I use 4.9.2.
I need to use aggregate because I will group by the result after processing the $match.
I already saw posts before, but manually casting didn't work for me!
Here is my schema:
var mongoose = require("mongoose");
var moment = require("moment");
var Schema = mongoose.Schema;
var AvgDailyCharging = new Schema({
_id : {
date: Date,
storeID: {
type: Schema.Types.ObjectId,
ref: 'store'
}
},
chargers: [{
transmitterID: {
type: Schema.Types.ObjectId,
ref: 'device'
},
minutes: Number
}],
});
mongoose.model('AvgDailyCharging', AvgDailyCharging);
And here is the query:
var Mongoose = require('mongoose');
var Model = require('../db/model');
var Query = require('../db/query');
var RESULT_LIMIT = 2000; // Limit the return data size
exports.getAvgDailyCharging = function(req, res) {
var id = new Mongoose.Types.ObjectId("58b43fdf0fd53910121ca6f4");
var query = new Query("AvgDailyCharging");
query.aggregate([
{
$match: {
"_id.storeID": id, //HELP!!!!!
"_id.date": { //match only by this works fine.
$gte: new Date(req.params.startTime),
$lt: new Date(req.params.endTime)
}
}
}
]).exec(function(error, data) {
if (error) {
res.send({result:'ERROR', message: error});
} else {
res.send(data);
}
});
}
Please help me!!!! I was stuck for several hours! Q_Q
When I was testing in mongoose version 4.4.4, both type casting and string didn't work. However, after I update it to the version 4.9.2, type casting is no needed, and directly using a string in $match _id works!
Update:2017-03-31
I think another problem in my scenario is my schema definition. Since this collection, say A, is created from another one, say B, using $group: { _id: { storeID: "$storeID" } } where the storeID field in collection B is of type ObjectId, then in collection A I find out that _id.store is actually a String not an ObjectId, so the best way is to change the schema I mentioned in the question to:
var AvgDailyCharging = new Schema({
_id : {
date: Date,
storeID: String
},
chargers: [{
transmitterID: {
type: Schema.Types.ObjectId,
ref: 'device'
},
minutes: Number
}],
});

Mongoose Populate Cast Error

I have the follwing schemas:
// online.js
var mongoose = require('mongoose');
// Online Friends
var onlineSchema = mongoose.Schema({
userid:{ type: Number, ref:'Player' }
},{timestamps : true});
// Export
module.exports = mongoose.model('Online', onlineSchema);
//player.js
var mongoose = require('mongoose');
// define the schema for player data
var playerSchema = mongoose.Schema({
userid : { type: Number, required: true,unique:true, default: 0 },
firstname : { type: String },
nick : {type: String, required: true},
lastname : {type: String},
lastupdate: {type: Date, default: Date.now}
},{timestamps : true});
// create the model and expose it to our app
module.exports = mongoose.model('Player', playerSchema);
//main.js
...
const Online = require('./config/models/online.js');
const Player = require('./config/models/player.js');
Online.find({userid:3441341}).populate('userid').exec(function(err,result){
if (err) {
console.log(err);
} else {
console.log(result);
}
});
...
I want to search Online for a userid and then print the name of the user, not exactly sure what I am doing wrong.
This is the error I'm getting:
MongooseError: Cast to ObjectId failed for value "3441341" at path "_id"
What is the proper way to achieve this ?
Change the userid type from Number to mongoose.Schema.ObjectId and it should work. It basically says you are trying to cast a number to Object Id. Pass the ids as strings.
In NoSQL DBS your documents must have _id field. Do you have a User model or do you use Player for the job? If you use Player as User model so change user_id to _id

Using a value of an document as _id when importing this document to MongoDB using NodeJS

I'm trying to import an Object into Mongo. But when I try to use a value of the Object as _id it fails. The error i.e: "[CastError: Cast to ObjectID failed for value "11563195" at path "_id"]" and later "[Error: document must have an _id before saving]"
What am I doing wrong ?
// Read and import the CSV file.
csv.fromPath(filePath, {
objectMode: true,
headers: keys
})
.on('data', function (data) {
setTimeout(function(){
var Obj = new models[fileName](data);
Obj._id = Obj.SOME_ID;
Obj.save(function (err, importedObj) {
if (err) {
console.log(err);
} else {
console.log('Import: OK');
}
});
}, 500);
})
Here is the used Schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var SomeSchema = new Schema(
{
SOME_ID: String,
FIELD01: String,
FIELD02: String,
FIELD03: String,
FIELD04: String,
FIELD05: String,
FIELD06: String,
FIELD07: String,
FIELD08: String,
FIELD09: String,
FIELD10: String,
FIELD11: String,
FIELD12: String,
FIELD13: String
},
{
collection: 'SomeCollection'
});
module.exports = mongoose.model('SomeCollection', SomeSchema);
Many thanks for your time and help.
By default mongoose is validating that the _id field is a MongoId. If you want to store something other than a MongoId in the _id field you will need to give the _id field a different type.
var SomeSchema = new Schema({
_id: { type: String, required: true }
}

Resources