Mongoose : Can't populate after find to make $near query - node.js

I am trying to populate user informations to get his location but i am getting undefined.
Here are my schemas:
AnnounceSchema:
const AnnounceSchema = new mongoose.Schema({
titre: String,
contenu: String,
image: String,
tag: String,
media: String,
date: {
type: Date,
default: Date.now
},
commentaires: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }],
authorId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
})
UserSchema:
const UserSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
email: { type: String, required: true, unique: true },
loc: { type: { type: String, default: 'Point' }, coordinates: { type: [Number] } }
});
UserSchema.index({ loc: '2dsphere' });
And here is my query :
Announce.find({})
.populate('authorId', null,
{
'authorId.loc': {
$near: {
$geometry: {
type: 'Point',
coordinates: [req.user.loc.coordinates[0], req.user.loc.coordinates[1]]
},
$maxDistance: 10000
}
}
})
.exec((err, announces) => {
if (err) {
res.send(err)
} else {
res.render('announce/search', { announces: announces })
}
})
The error I'm getting is "unable to find index for $geoNear query". I've added an index to the AnnonceSchema but no change:
AnnonceSchema.index({ "authorId.loc" : "2dsphere"})

This should work:
Announce.find({})
.populate('author',
{
path : 'authorId',
match: {
'loc': {
$near: {
$geometry: {
type: 'Point',
coordinates: [req.user.loc.coordinates[0], req.user.loc.coordinates[1]]
},
$maxDistance: 10000
}
}
},
model: 'User',
})
.exec((err, announces) => {
if (err) {
res.send(err)
} else {
res.render('announce/search', { announces: announces })
}
})
populate works in two ways
it can populate by reference Announce.find({}).populate('authorId')
or by a custom query (which is what you need)

Related

Node.js with mongoose delete one array element

I am trying to delete one array element when I click delete button on jade view page.
When clicked, it's going to send selected instructor objected as req.body.
At sever side, it will find courses that contain the instructor objectId.
Any idea for me?
Thank you for reading it.
here is my code:
var id = req.body._id;
clist.find({ instructors: { $in: [id] } }).exec(function (err, result) {
result.forEach(function (obj) {
clist.update(
{ _id: new mongoose.Types.ObjectId(obj._id)},
{ $pull: { instructors : [new mongoose.Types.ObjectId(id)] } }
);
console.log(new mongoose.Types.ObjectId(obj._id) + ' was deleted');
});
});
Schema Clist and ilist:
var instructorlist = mongoose.Schema({
name: { type: String, required: true },
age: { type: Number, required: true },
gender: { type: String, required: true },
DOB: { type: Date, required: true, default: Date.now },
email: { type: String, required: true },
phone: { type: Number, required: true },
address: { type: String, required: true },
dateofstart: { type: Date, required: true},
courses: [{
type: mongoose.Schema.Types.ObjectId,
ref: "clist"
}]
});
var courselist = mongoose.Schema({
coursename: { type: String, required: true },
coursenumber: { type: String, required: true },
coursecredit: { type: Number, required: true },
courseroom: { type: String, required: false },
courseregisteddate: {type: Date, default: Date.now},
students: [{
type: mongoose.Schema.Types.ObjectId,
ref: "slist"
}],
instructors: [{
type: mongoose.Schema.Types.ObjectId,
ref: "ilist"
}]
});
one example for mongodb :
{
"_id": {
"$oid": "591a7a3b391a1842e8a69e23"
},
"coursename": "JDKD",
"coursenumber": "COMP4483",
"coursecredit": 4,
"courseroom": "sdaf",
"instructors": [
{
"$oid": "591a374422a3a13d38c0bbe5"
}
],
"students": [],
"courseregisteddate": {
"$date": "2017-05-16T04:04:11.848Z"
},
"__v": 0
}
When I add instructor objectID in Course.
var newcourse = new clist({
'coursename': req.body.coursename, 'coursenumber': req.body.coursenumber, 'coursecredit': req.body.coursecredit
, 'courseroom': req.body.room, 'instructors': instructors._id
});
Use same operation to find and update multiple
clist.update(
{ instructors: { $in: [id] }},
{ $pull: { instructors : { _id : new mongoose.Types.ObjectId(id) } } }, //or{ $pull: { instructors: mongoose.Types.ObjectId(id) } }
{
multi:true
},
function(error, success){
if(error){
console.log("error",error)
}
console.log("success",success)
});

Mongoose: How to findById when the query is not complete

I am building a search query where it will find a database object by its ID even while the user is typing.
ordersRouter.route('/searchorder/:term')
.get(function(req, res){
term = req.params.term;
console.log(term);
Orders.findById(term)
.populate({ path: 'userPurchased products.product', select: '-username -password' })
.exec(function(err, orders){
if (err) throw err;
res.json([orders]);
});
});
The problem here is that when the term does not exactly the same as the ID, it will return nothing. How can I return IDs with partial term?
EDIT: My order model schema
var orderSchema = new Schema({
orderId: { type: String },
userPurchased: { type: Schema.Types.ObjectId, ref: 'users' },
products: [
{
product: { type: Schema.Types.ObjectId, ref: 'products' },
size: { type: String, required: true },
quantity: { type: Number, required: true },
subTotal: { type: Number, required: true }
}
],
totalQuantity: { type: Number },
totalPrice: { type: Number },
modeOfPayment: { type: String },
shippingAd: { type: String },
refNumber: { type: String },
isDone: { type: Boolean, default: false },
orderStatus: { type: String, default: 'Pending' },
dateOrdered: { type: Date, default: Date.now() },
fromNow: { type: String }
});
You can run your query using regex i.e. create a regular expression object from the string using the RegExp constructor then run the query as:
ordersRouter.route('/searchorder/:term')
.get(function(req, res){
term = req.params.term;
console.log(term);
Orders.find({'orderId': new RegExp(term)})
.populate({
path: 'userPurchased products.product',
select: '-username -password'
})
.exec(function(err, orders){
if (err) throw err;
res.json(orders);
});
});

Populate on basis of condition in mongoose, mongoDB

Here is my code to get one floorplan and populate all flats linked with this
see the code below :
var floorplan = Floorplan.find({
project: req.params.project,
tower: req.params.tower,
isDeleted: false
});
floorplan.populate('flats').exec(function(err, floorplan) {
if (err) { return res.send(err); }
if (!floorplan) { return res.status(401).json(); }
res.status(200).json(floorplan);
});
But I want to populate only those flats where isDeleted : false
How to achive this ??
Schema of floorplan
var FloorplanSchema = new Schema({
project: { type: Schema.ObjectId, ref: "Project" },
flats: [{ type: Schema.ObjectId, ref: "Flat" }],
tower: [{ type: Schema.ObjectId, ref: "Tower" }],
unitType: String,
area: Number,
floorPlan2D: String,
floorPlan3D: String,
livingRoomArea: Number,
kitchenArea: Number,
balconies: Number,
bathRooms: Number,
isDeleted: { type: Boolean, 'default': false },
createdAt: { type: Date, 'default': Date.now }
});
Schema of flat
var FlatSchema = new Schema({
tower: { type: Schema.ObjectId, ref: "Tower" },
floorplan: { type: Schema.ObjectId, ref: "Floorplan" },
project: { type: Schema.ObjectId, ref: "Project" },
status: String,
floor: Number,
size: String,
superbuiltup_area: Number,
directionFacing: String,
furnishingState: String,
flooringType: String,
createdAt: { type: Date, 'default': Date.now },
isDeleted: { type: Boolean, 'default': false },
});
The populate() method has an option which allows for filtering, you can either try this
Floorplan
.find({
project: req.params.project,
tower: req.params.tower,
isDeleted: false
})
.populate({
path: 'flats',
match: { isDeleted: false }
})
.exec(function(err, floorplan) {
if (err) { return res.send(err); }
if (!floorplan) { return res.status(401).json(); }
res.status(200).json(floorplan);
});
or
Floorplan
.find({
project: req.params.project,
tower: req.params.tower,
isDeleted: false
})
.populate('flats', null, { isDeleted: false })
.exec(function(err, floorplan) {
if (err) { return res.send(err); }
if (!floorplan) { return res.status(401).json(); }
res.status(200).json(floorplan);
});

Mongoose - Cast to ObjectId failed for value "[object Object]" at path _id

I have the below schema:
var StorySchema = new Schema({
title: { type: String, required: true },
users: {
id: { type: Schema.ObjectId, ref: 'users' },
creator: { type: Boolean }
},
maxlines: { type: Number, default: '10'},
lines: {
text: { type: String },
entered_at: { type: Date },
user: {
id: { type: Schema.ObjectId, ref: 'users' }
}
},
created_date: { type: Date, default: Date.now },
updated_date: { type: Date, default: Date.now },
})
I've got the below which does the query:
exports.view = function (req, res) {
Stories
.findOne({
_id: req.params.id
})
/*.populate('users') */ **<-- If I uncomment this I get the error**
.exec(function (err, story) {
if (err) {
res.json(200, {
success: "false",
message: err.message
})
} else if (story) {
res.json({
sucess: "true",
message: story
})
} else {
res.json(200, {
sucess: "false",
message: "story not found"
})
}
})
}
As above if I add .populate('users') it flags the below error:
{
"success": "false",
"message": "Cast to ObjectId failed for value \"[object Object]\" at path \"_id\""
}
I'm calling /view/51fc2e02576f2dc058000001 (which is an Object ID of the stories table), without the .populate('users') if I call the URL it brings back the document.
The users -> id value is populated with ObjectId("51fbe87ec137760025000001") - which is a valid _id in the users collection
I cannot see what I'm missing?
Added User Schema
var UserSchema = new Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
username: { type: String, required: true, unique: true },
provider: { type: String, required: true, enum: ['local', 'facebook'] },
password: { type: String, required: true },
avatar: { type: String, default: 'http://i.imgur.com/1PtcFos.jpg' },
gender: { type: String, required: true, uppercase: true, enum: ['M', 'F'] },
facebook: {
id: { type: String },
token: { type: String },
token_expiry: { type: Date }
},
device: {
token: { type: String },
type: { type: String, enum: ['ios', 'android'] },
badge: { type: Number },
id: { type: String },
created_date: { type: Date, default: Date.now },
updated_date: { type: Date, default: Date.now }
},
created_date: { type: Date, default: Date.now },
updated_date: { type: Date, default: Date.now }
})
I think you can only do .populate('users.id'). Populate is to use the reference Object to replace the id field. Please take a look at the doc.

mongoose save embedded document

I have the following schema:
var StorySchema = new Schema({
title: { type: String, required: true },
users: {
id: { type: Schema.ObjectId, ref: 'Users' },
creator: { type: Boolean }
},
maxlines: { type: Number, default: '10'},
lines: {
text: { type: String },
entered_at: { type: Date },
user: {
id: { type: Schema.ObjectId, ref: 'Users' }
}
},
created_date: { type: Date, default: Date.now },
updated_date: { type: Date, default: Date.now },
})
I want to push data into lines and am trying to do so with the below update:
exports.update = function (req, res) {
Stories
.findOne({ _id: req.params.id }, function (err, story) {
if (err) {
res.json(200, {
success: "false",
message: err.message
})
} else {
story.maxlines = story.maxlines - 1
story.lines.push ({
text : req.body.text,
'user.id' : req.headers.id,
entered_at : new Date().toISOString()
})
story.save(function(err, story) {
if (err) {
res.json(200, {
success: "false",
message: err.message
})
} else if (story) {
res.json({
sucess: "true",
message: story
})
}
})
}
})
}
I get an error of TypeError: Object { user: {} } has no method 'push', not entirely sure how to update the lines and the user associated with the line
Because story.lines is not an Array. You probably need to update the Schema to convert the lines to type Array in this way:
var LineSchema = new Schema({
text: {
type: String
},
entered_at: {
type: Date
},
user: {
id: {
type: Schema.ObjectId,
ref: 'Users'
}
}
});
var StorySchema = new Schema({
title: {
type: String,
required: true
},
users: {
id: {
type: Schema.ObjectId,
ref: 'Users'
},
creator: {
type: Boolean
}
},
maxlines: {
type: Number,
default: '10'
},
lines: [LineSchema],
created_date: {
type: Date,
default: Date.now
},
updated_date: {
type: Date,
default: Date.now
},
})

Resources