`_id` in where clause - mongodb

I face an issue trying to access _id in a query.where.
My schema:
var testSchema = new Schema({
test2id: [{ type: Schema.Types.ObjectId, ref: 'Test2' }],
test3id: [{ type: Schema.Types.ObjectId, ref: 'Test3' }]
});
var test2Schema = new Schema({
name: String
});
var test3Schema = new Schema({
name: String
});
My query:
testSchema.statics.findByid = function (id, callback) {
var query = this.findOne();
Test2.findOne({'name': name}, function (error, t2) {
query.where({
test2id: _id,
}).exec(callback);
});
return query
};
_id is undefined, I try also this._id but the query return null.
I just want to get all documents from testSchema with test2id = _id of the testSchema document.
Any idea to fix that and access to _id from a query.where clause?

I finally resolve it by passing it in parameter.
var test = new Test();
test.findByid(test._id, req.params.id, function(err, res) {
...
});

Related

Overriding Mongoose _id and using properties directly from the schema

I need to create a patient model and override the _id property. I know I can override it by writing a schema like so:
const PatientSchema: Schema = new Schema({
_id: {type: String, required: true},
name: { type: String, required: true },
surname: { type: String, required: true },
provider: { type: Schema.Types.ObjectId, ref: "Provider" },
});
Is there a way to define the _id property inside the schema to reference the name + surname properties?:
_id: name+surname, (?)
or do I have to explicitly define it when creating and saving a new model?:
const patient = new Patient();
patient._id = name+surname;
Also, what should I consider if patients have the same name and surname? What is considered best practice in this case if the _id needs to = name + surname?
Thanks
you could use mongoose pre-save middleware in your schema
Basically, middlewares are functions that are called during the execution of a model query/method.
there are 2 types of middleware :
"pre" middlewares that are executed before the query
"post" middlewares that are executed after the query.
syntax :
schema.pre([method], function (next) {
console.log("pre middleware")
next();
});
schema.post([method], function (next) {
console.log("post middleware")
next();
});
/*[method] can be
"save","updateOne","findOne","findOneAndUpdate",etc...*/
//"pre" will always be executed before "post"
And depending on the method you are going to use, middlewares can change in the value of "this", there are 4 types of these:
where "this" refers to the document E.g."save"
where "this" refers to the query E.g."findOne"
where "this" refers to an aggregate E.g." aggregate"
where "this" refers to the model. E.g. "insertMany"
Solution :
const PatientSchema = new Schema({
_id: { type: String },
name: { type: String, required: true },
surname: { type: String, required: true },
provider: { type: Schema.Types.ObjectId, ref: "Provider" },
});
//will change _id before save
PatientSchema.pre("save", async function (next) {
try {
const patient = this; //the target document
patient._id = patient.name + " " + patient.surnam
next()
}
catch (err) { next(err) }
});
module.exports = model("Patients", PatientSchema);
and when you create a patient it will have the id based on the combination of their first and last name
const patient = new Patient({
name: "John",
surname: "smith"
})
await patient.save();
result : {
_id: "John smith ";
name: "John";
surname: "smith";
__v: 0;
}
[ Edit ]
if you want your id to be unique you could create an ObjectId and concatenate
it to the final id
const { ObjectId } = require("mongodb");
PatientSchema.pre("save", async function (next) {
try {
const patient = this; //the target document
const objectId = ObjectId();
patient._id = `${patient.name} ${patient.surname} ${objectId}`;
next();
} catch (err) {
next(err);
}
});

Mongoose Populate a field

I have two mongoose schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var itemSchema = new Schema({
name: {type: String, required: true, max: 25, trim: true},
price: {type: Number, required: true, trim: true, default: 0},
tax: {
type: Schema.Types.ObjectId,
ref: "Store"
}
});
module.exports = mongoose.model('Item', itemSchema);
The second Schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var storeSchema = new Schema({
name: {type: String, required: true, trim: true},
taxes: [
{
name: String,
rate: Number
}
]
});
module.exports = mongoose.model('Store', storeSchema);
What I want to do is populate the itemSchema tax object with the storeSchema taxes array of object. every time I pushed a new tax object to the taxes array mongoose created an ObjectId. I stored that ObjectId in my itemSchema Tax. I want to use that _id to retrieve the store taxes that matches the itemSchema _id.
I have tried this so far, but I get no in the tax attribute.
Item.find().populate("tax", "taxes").exec(function (err, docs) {
if (err) return console.error(err);
console.log(items);
});
Try this query
Item.find().populate({
path: 'tax',
select: 'taxes'
}).exec(function (err, docs) {
if (err) {
console.error(err);
} else {
console.log(docs);
}
});
Item.find().populate(path:"tax", model: )
Mention your item model file name... don't use "" or '' for the file name, simply add the file name.
Use Item.find().populate("Store", "taxes") instead of Item.find().populate("tax", "taxes").

null results of search by _id in mongoose

I'm getting [] res in mongoose find by {parentId: cat._id}
var ObjectId = Schema.ObjectId;
var CategorySchema = new Schema({
name: String,
slug: String,
parentId: {type: ObjectId, required: false},
ancestors: {
type: [{
_id: ObjectId,
name: String,
slug: String
}], required: false
}
});
CategorySchema.statics.getNested = function(parentSlug,cb){
this.findOne({slug:parentSlug},function(err,cat){
if (err) {
cb(err);
} else {
this.find({parentId: cat._id},function(err, cats){
console.log(cats);
if (err){
cb(err);
} else {
cb(null,cats);
}
});
}
});
};
I tried {parentId: ObjectId(cat._id)} but this did not work too // ObjectId(cat._id) -> undefined
How do I search mongoose by _id?
UPDATE!
The query
Category.find({parentId:'5634eeb38a33a59c1dffa6ee'}, function(err,res){
console.log(res);
});
is working fine but how?
It should be {parentId: mongoose.Types.ObjectId(cat._id)}
You have incorrect ObjectId type in your schema, you should use Schema.Types.ObjectId instead of Schema.ObjectId because they return different values:
http://mongoosejs.com/docs/api.html#schema-objectid-js
http://mongoosejs.com/docs/api.html#types-objectid-js
If you replace your ObjectId definition to the following
var ObjectId = Schema.Types.ObjectId;
your code should work correctly.

mongodb relations find one with all their related

I know how to get data with their related
var UserSchema = new Schema({
username: String
});
var PostSchema = new Schema({
title: String,
author: {type: Schema.Types.ObjectId, ref: 'User'}
});
...
Post.findOne({_id: id})
.populate('author')
.exec(function(error, result) {
// do stuff
})
but how to do the opposite?
I mean when I want a user, with all their posts with single query?
Try adding a filter step after the query returns that manually filters out documents which don't have any posts that matched the populate criteria:
var username = "foo";
Post.find()
.populate('author', null, {username: username})
.sort({'_id': 1})
.exec(function (err, posts) {
posts = posts.filter(function(post){
return post.author.length;
});
res.send(posts);
});

How can I store data other than ObjectId using Mongoose populate?

Taking the example from here
http://mongoosejs.com/docs/populate.html
If I try to tweak it so that 'fans' also contains a rating
var db = require('houselib/db');
var Schema = db.Schema;
var mongoose = db.mongoose;
var PersonSchema = new Schema({
name : String
, age : Number
, stories : [{ type: Schema.ObjectId, ref: 'Story' }]
});
var StorySchema = new Schema({
_creator : { type: Schema.ObjectId, ref: 'Person' }
, title : String
, fans : [{ type: Schema.ObjectId, ref: 'Person', rating: Number}]
});
var Story = mongoose.model('Story', StorySchema);
var Person = mongoose.model('Person', PersonSchema);
var aaron = new Person({ name: 'Aaron', age: 100 });
aaron.save(function (err) {
if (err) throw err;
var story1 = new Story({
title: "A man who cooked Nintendo"
, _creator: aaron._id
, fans: [{type: aaron._id, rating: 4}]
});
story1.save(function (err) {
if (err) throw err;
Story
.find({ _creator: aaron._id })
.populate('_creator') // <-- not really necessary
.run(function (err, stories) {
if (err) throw err;
console.log('The stories JSON is an array: ', stories);
})
});
})
I get the following error
CastError: Cast to undefined failed for value "[object Object]"
The documentation says that manual linking is preferred over DBRef
http://www.mongodb.org/display/DOCS/Database+References#DatabaseReferences-SimpleDirect%2FManualLinking
story.fans is an array of objectids. objectids do cannot have ratings. You need to add the rating to the Person schema instead of the story schema.
var PersonSchema = new Schema({
name : String
, age : Number
, rating: Number
, stories : [{ type: Schema.ObjectId, ref: 'Story' }]
});