MongoError: can't get query executor with geoNear Mongoose - node.js

I am trying to get results from DB using geoNear in Moongose but it is giving "can't get query executor" error.
// Schema
let dealSchema = new Schema({
userId: {type: String, required: true},
images: {type: [String], required: true},
location: {
lng: {type: Number},
lat: {type: Number},
name: {type: String, required: true}
},
description: {type: String, required: false, default: ""},
expiredReports: {type: [String], required: false},
inappropriateReports: {type: [String], required: false},
likes: {type: [String], required: false},
dislikes: {type: [String], required: false},
comments: {type: [commentSchema], required: false},
creationDate: {type: Date, default: new Date()},
updationDate: {type: Date, default: new Date()}
}, {collection: TableName.DEAL});
function getAll(radius) {
var point = {type: "Point", coordinates: [9, 9]};
let distance = parseInt(radius);
if (isNaN(distance)) {
return callback(new Error("Invalid Radius"), null)
}
var geoOptions = {
spherical: true,
maxDistance: distance,
num: 10
};
DealData.geoNear(point, geoOptions, function (err, docs, stats) {
console.log(docs);
}
);
}
This is my model of Mongoose and My code to get data from Database.

geoNear method requires 2dsphere index, after creating that index you'll be able to querying data by coords.
Example:
var mySchema = new mongoose.Schema({
name: {type: String, required: true},
location: {type: [Number], index: '2dsphere'}
});
The first item of the location field is longtitude and the second one is latitude

Related

How do I use nested schemas in mongoose, using 'type', to create arrays?

I am trying to create a nested mongoose schema that uses 'type' to create a nested array.
The schema that I think I am having an issue with is "chorePerson".
Here is the data that I am trying to put into a schema:
{
"chart": [
{
"ordinal": 0,
"chorePerson": [
{
"person": "emily",
"chore": "Catbox"
},
{
"person": "Steve",
"chore": "Dishes"
}
]
}
]
Here is my current schema. Note the use of "type" for "chart" and "chorePerson"
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const chorePersonSchema = new mongoose.Schema({
person: {type: String, requried: true},
chore: {type: String, required: true},
});
const chartSchema = new mongoose.Schema({
ordinal: {type: Number, required: true},
chorePerson:{ type: chorePersonSchema },
});
// create the schema
const ChoreChartSchema = new Schema({
affiliation: {type: String, required: true},
currentWeekNumber: {type: Number, required: true},
currentYear: {type: Number, required: true},
chart:{ type: chartSchema },
date: {type: Date, default: Date.now},
})
module.exports = ChoreChart = mongoose.model('cm_chorechart', ChoreChartSchema)
When I run my code this is what I get before the crash:
{ _id: 5c742ed116a095522c38ddfc,
affiliation: 'family',
currentYear: 2019,
currentWeekNumber: 9,
date: 2019-02-25T20:26:33.914Z,
chart: [ { ordinal: 0, chorePerson: [Array] } ] }
I think... chorePerson is causing the error... but I don't know how to fix it.
Here is the exception:
(node:6728) UnhandledPromiseRejectionWarning: ObjectExpectedError: Tried to set nested object field `chart` to primitive value `[object Object]` and strict mode is set to throw.
What I have tried
I tried this schema:
const chartSchema = new mongoose.Schema({
ordinal: {type: Number, required: true},
chorePerson : [{
person : String,
chore : String
}]
});
Update:
OK... so I went back to basics and this works, but it's not how I want the final schema to be. Can anybody help out with nesting this ?
// create the schema
const ChoreChartSchema = new Schema({
affiliation: {type: String, required: true},
currentWeekNumber: {type: Number, required: true},
currentYear: {type: Number, required: true},
// chart:{ type: chartSchema },
chart:[{
ordinal: 0,
chorePerson : [{
person : String,
chore : String
}]
}],
date: {type: Date, default: Date.now},
})
Turns out it was easier than I thought:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const chorePersonSchema = new mongoose.Schema({
person: {type: String, requried: true},
personID: {type: String, required: true},
chore: {type: String, required: true},
choreID: {type: String, required: true},
});
const chartSchema = new mongoose.Schema({
ordinal: {type: Number, required: true},
chorePerson : [{ type:chorePersonSchema }]
});
// create the schema
const ChoreChartSchema = new Schema({
affiliation: {type: String, required: true},
weekNumber: {type: Number, required: true},
year: {type: Number, required: true},
chart:[{type: chartSchema}],
date: {type: Date, default: Date.now},
})
module.exports = ChoreChart = mongoose.model('cm_chorechart', ChoreChartSchema)

Mongodb lookup with two ObjectId

I have a little issue getting lookup to work. It returns an empty array. I use contactId field in Billing Collection. And I use the contact _id created when entry in Contact Collection in mongodb (Can see it in Robomongo). I have few Billings with ContactId corresponding to the _id of few Contacts. Is my syntaxe correct ? Do I miss something ? Thank you for your help.
Below is my lookup syntaxe
Contact.aggregate([
{
$lookup: {
from: "Billing",
localField: "_id",
foreignField: "contactId",
as: "BillingMembership"
}
}
]).exec(function (err, contacts) {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
res.status(200).json({
message: 'Success',
obj: contacts
});
});
Below is the result I get back from the database.
(4) [Object, Object, Object, Object]
0:Object
BillingMembership:Array(0)
length:0
__proto__:Array(0)
additionalInterests:"MFM/REI"
billingEmail:"john#netdr.net"
cellPhone:6787025500
dateBirth:"1555-02-02T00:00:00.000Z"
firstName:"qtazerqr'efsg"
gogsMbrType:"Resident Applicant"
gogsYearJoined:"20111"
homePhone:6787025500
lastName:"gzaetrsg"
memberSuffix:", DO"
middleName:"fzerqgrre"
notes:"htrfjghdnt"
officeEmail:"john#netdr.net"
officePhone:6787025500
personalEmail:"john#netdr.net"
practiceId:"592e4c1638a494089c50c8c8"
praticeType:"MFM/High Risk"
spFirstNm:"gsertdhy"
spLastNm:"rthytrfgj"
spSuffix:"syhtdrh"
website:"trshdty"
__v:0
_id:"5932db29eb4dfe0de4a8a36d"
__proto__:Object
1:Object
2:Object
3:Object
Mongoose Schema Contact
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var mongooseUniqueValidator = require('mongoose-unique-validator');
var schema = new Schema({
firstName: {type: String, required: true},
middleName: {type: String, required: true},
lastName: {type: String, required: true},
dateBirth: {type: Date, required: true},
memberSuffix: {type: String, required: true},
officePhone: {type: Number, required: true},
homePhone: {type: Number, required: true},
cellPhone: {type: Number, required: true},
officeEmail: {type: String, required: true},
billingEmail: {type: String, required: true},
personalEmail: {type: String, required: true},
gogsMbrType: {type: String, required: true},
gogsYearJoined: {type: String, required: true},
spFirstNm: {type: String, required: true},
spLastNm: {type: String, required: true},
spSuffix: {type: String, required: true},
notes: {type: String, required: true},
praticeType: {type: String, required: true},
additionalInterests: {type: String, required: true},
website: {type: String, required: true},
practiceId: {type: Schema.Types.ObjectId, ref: 'Practice'}
});
schema.plugin(mongooseUniqueValidator);
module.exports = mongoose.model('Contact', schema);
Mongoose Schema Billing
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var mongooseUniqueValidator = require('mongoose-unique-validator');
var schema = new Schema({
reason: {type: String, required: true},
amount: {type: Number, required: true},
membership: {type: String, required: true},
membershipYear: {type: Schema.Types.ObjectId, ref: 'Membership'},
type: {type: String, required: true},
date: {type: String, required: true},
contactId: {type: Schema.Types.ObjectId, ref: 'Contact'},
conferenceId: {type: Schema.Types.ObjectId, ref: 'Conference'}
});
schema.plugin(mongooseUniqueValidator);
module.exports = mongoose.model('Billing', schema);
Solved. thanks to Veeram.
I used Change your from: "Billing" to from: "billings"

Schema Association in Mongoose

I have 2 models:
Here is the User Model:
const userSchema = new mongoose.Schema({
email: { type: String, unique: true, required: true },
password: { type: String, required: true },
passwordResetToken: String,
passwordResetExpires: Date,
facebook: String,
twitter: String,
tokens: Array,
profile: {
name: String,
gender: String,
location: String,
website: String,
picture: String
}
}, { timestamps: true });
And here is the Revive Model:
const reviveSchema = new mongoose.Schema({
reviveShowName: {type: String, required: true},
reviveTitle: {type: String, required: true},
reviveCategory: {type: String, required: true},
reviveGoal: {type: Number, required: true},
revivePhoto: {type: String, required: true},
reviveVideo: {type: String},
reviveStory: {type: String},
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
name: String
}
}, { timestamps: true });
In the Revive model, I'm trying to the reference the author and get the author's id and that works... How do I also get the name from profiles -> name...? Clearly name: String is wrong...
Mongoose relations work, based on the ref and type value of the nested object. In your case you have associated the id property of author to point to the User model.
If you want to populate the author with the user information, you should just do :
author: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}
Then in your query you just use populate
Revive.find({})
.populate( 'author' )
.exec( function( error, docs ) {
console.log( docs ); // will have `[{author:{profile:{...}}}]` data
} );

How to do `$text` search on one collection to get the data from the other collection?

I need to provide search for e-commerce site. In that there is a 4-level menu like this category>>subcategory>>product>>subproduct. I had divided them into 3 schemas like this
category schema
var categorySchema = new mongoose.Schema(
{
"catname": {type: String, required: true},
}
);
mongoose.model('category',categorySchema);
subcategory and product schema
var productSchema = new mongoose.Schema(
{
"catid": {type: mongoose.Schema.Types.ObjectId, ref: 'category'},
"subcatname": {type: String, required: true},
"product":[
{
"productname":{type:String},
}
]
}
);
mongoose.model('product',productSchema);
subproduct schema
var subproductSchema = new mongoose.Schema(
{
"productid": {type: mongoose.Schema.Types.ObjectId, ref: 'products', required: true},
"itemcode": {type: String, required: true},
"itemname": {type: String, required: true/*, index: "text"*/},
"itemdescription": {type: String, required: true},
"itemimgurl": {type: String, required: true},
"mainprice": {type: Number},
"offerprice": {type: Number, required: true},
"unit": {type: String, required: true},
"stock": {type: Number, required: true},
"offertag": {type: String},
"itemprice":[
{
"itemname" :{type: String, required: true},
"unit": {type: String, required: true},
"offerprice": {type: Number, required: true},
"mainprice": {type: Number},
"stock": {type: Number, required: true},
"notify": {type: Number, required: true},
"status": {type: Boolean, required: true},
"itemimgurl": {type: String},
"offertag": {type: String}
}
]
}
);
mongoose.model('subproduct',subproductSchema);
I need to give the subproducts corresponding to the users search, like if the user searches with the catname or subcatname or productname or itemname need to give the related subproducts. How can I achieve this with mongoose?
This is with reference to the question you asked in the comment.
If you want to search for an incomplete query or a word, i will provide a small code, which will help you.
var query = req.body.query; //the string you take for search
var filter = {
$or: [
{subcatname: new RegExp('.*' + query, 'i')},
{productname: new RegExp('.*' + query, 'i')},
//similarly you can put more cases
]
}
subproducts.find(filter, function(err, data){
if(err){console.log(err);}
console.log(data);
});

Complex query with mongoose, including subdocuments, near condition,

I have a very (at least for me) complex query using Mongoose.
First of all my schema:
var ObjectSchema = new Schema({
pickupStartDate: {type: Date, required: true, default: Date},
pickupEndDate: {type: Date, required: true, default: Date},
...
handoverStartDate: {type: Date, required: true, default: Date},
handoverEndDate: {type: Date, required: true, default: Date},
...
});
By using the "plugin mechanism" my Object has two addresses (called pickupAddress and handoverAddress. The address looks like that:
var name = 'address';
var obj = {};
obj[name] = {
street: String,
zipCode: String,
city: String,
state: String,
country: String,
loc: {type: [Number], index: '2dsphere'}
};
schema.add(obj);
And the other schema:
var TripSchema = new Schema({
startDate: {type: Date, required: true, default: Date},
endDate: {type: Date, required: true, default: Date},
handoverRadius: {type: Number, required: true}
});
It has an address, too (using plugin mechanism again).
I want the following query:
Find all "objects" which "fit" to my trip.
"Fit" means:
handoverStartDate >= trip.startDate
handoverEndDate <= trip.endDate
`handoverAddress is near trip.address
...
I thought this would be a good approach:
ObjectSchema
.find()
.and([
{ handoverStartDate: {$gte: trip.startDate}},
{ handoverEndDate: {$lte: trip.endDate}},
{ 'handoverAddress.loc': {$near: {
'$maxDistance': 10 * 1000,
'$center': {
type: 'Point',
coordinates: trip.address.loc
}
}}}
])
.exec(function(err, cdObjects) {
console.log(err);
console.log(cdObjects);
});
But this leads to the following error:
{ message: 'Cast to number failed for value "[object Object]" at path "handoverAddress.loc"'.
I guess because of 'handoverAddress.loc'. But I'm not sure how to specify that as it has to be a string (because it's a subdocument).
You don't need the and. try
ObjectModel.find({
handoverStartDate: {$gte: trip.startDate},
handoverEndDate: {$lte: trip.endDate},
'handoverAddress.loc': {
$near: {
$geometry: {
type: "Point",
coordinates: trip.address.loc
},
$maxDistance: 10 * 1000
}
})
Make sure trip is defined as a variable and that startDate,endDate, and address are all defined properties fitting your expectations.
This is how it worked for me:
ObjectSchema
.where('handoverStartDate').gte(trip.startDate)
.where('handoverEndDate').lte(trip.endDate)
.where('handoverAddress.loc').near({
center: {
type: 'Point',
coordinates: trip.address.loc
},
maxDistance: 10 * 1000
});

Resources