I'm trying to get a Mongoose scheme to perform point based $near finds. I'm just trying to obtain random documents and I'm getting guide from this answer.
I've tried:
Video.where('randomTag').near({
center: {
type: 'Point',
coordinates: [-98.18, 19]
}
}).exec(function (err, videos) {
console.log(err)
response.json(videos);
})
Also:
Video.near('randomTag',{
center: {
type: 'Point',
coordinates: [-98.18, 19]
}
}).exec(function (err, videos) {
console.log(err)
response.json(videos);
})
And:
Video.find({
randomTag: {
$near: {
$geometry: {
type: "Point",
coordinates: [Math.random()/Math.random(), 0]
}
}
}
}).exec(function (err,videos) {
response.json(videos)
})
And for all those attemps I got this error:
error: Can't use $near with Number.
I already got the required index:
{randomTag: '2dsphere'}
The schema looks like:
{
videoId: String,
randomTab: Array(Number),
title: String,
playCount: Number
}
Here is some sample data.
{
"videoId": "aRDAz55d-y",
"randomTag": [2.255285185646381,0],
"title": "La décima, inolvidable",
"playCount": 254111
}
{
"videoId": "vAFj32af",
"randomTag": [0.4515513067517708,0],
"title": "SILePetitPrince",
"playCount": 900
}
This is whole error trace:
Error: Can't use $near with Number.
at SchemaNumber.castForQuery (/storage/home/dev/final-cut/node_modules/mongoose/lib/schema/number.js:261:13)
at module.exports (/storage/home/dev/final-cut/node_modules/mongoose/lib/cast.js:196:39)
at Query.cast (/storage/home/dev/final-cut/node_modules/mongoose/lib/query.js:2341:10)
at Query.find (/storage/home/dev/final-cut/node_modules/mongoose/lib/query.js:998:10)
at Function.find (/storage/home/dev/final-cut/node_modules/mongoose/lib/model.js:1026:13)
at sayHello (/storage/home/dev/final-cut/api/controllers/api.js:23:15)
at Layer.handle [as handle_request] (/storage/home/dev/final-cut/node_modules/express/lib/router/layer.js:95:5)
at next (/storage/home/dev/final-cut/node_modules/express/lib/router/route.js:131:13)
at Route.dispatch (/storage/home/dev/final-cut/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/storage/home/dev/final-cut/node_modules/express/lib/router/layer.js:95:5)
at /storage/home/dev/final-cut/node_modules/express/lib/router/index.js:277:22
at Function.process_params (/storage/home/dev/final-cut/node_modules/express/lib/router/index.js:330:12)
at next (/storage/home/dev/final-cut/node_modules/express/lib/router/index.js:271:10)
at Function.handle (/storage/home/dev/final-cut/node_modules/express/lib/router/index.js:176:3)
at router (/storage/home/dev/final-cut/node_modules/express/lib/router/index.js:46:12)
at Layer.handle [as handle_request] (/storage/home/dev/final-cut/node_modules/express/lib/router/layer.js:95:5)
GET /api/hello 500 20.560 ms - -
The reason of the Math.random() use is because of the randomness need. Is there something I'm missing?
Looks good to me. You must be doing something different to this listing:
var async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
var videoSchema = new Schema({
videoId: String,
randomTag: [Number],
title: String,
playCount: Number
});
videoSchema.index({ "randomTag": "2dsphere" });
var Video = mongoose.model( 'Video', videoSchema );
mongoose.connect('mongodb://localhost/test');
mongoose.set("debug",true);
Video.find(
{
"randomTag": {
"$near": {
"$geometry": {
"type": "Point",
"coordinates": [Math.random()/Math.random(),0]
}
}
}
},
function(err,videos) {
if (err) throw err;
console.log(videos);
mongoose.disconnect();
}
);
Which gives me results like this:
Mongoose: videos.ensureIndex({ randomTag: '2dsphere' }) { background: true }
Mongoose: videos.find({ randomTag: { '$near': { '$geometry': { type: 'Point', coordinates: [ 1.8434117849022023, '\u001b[33m0\u001b[39m' ] } } } }) { fields: undefined }
[ { playCount: 254111,
title: 'La décima, inolvidable',
randomTag: [ 2.255285185646381, 0 ],
videoId: 'aRDAz55d-y',
_id: 5627616d76dfa5adcd39fd38 },
{ playCount: 900,
title: 'SILePetitPrince',
randomTag: [ 0.4515513067517708, 0 ],
videoId: 'vAFj32af',
_id: 5627616d76dfa5adcd39fd39 } ]
Related
This is my Conversation Schema
const ConversationSchema = new Schema({
recipients: [{ type: Schema.Types.ObjectId, ref : 'User' }],
lastMessage: {
type: String,
default: ''
},
date: {
type: Date,
default: Date.now()
},
})
I want to know if there exist an array [ patientId, doctorId ]
Here is my main approach to find
I am not able to get the response and I already have one document with that same array
const conversationBetween = await Conversation.findOne(
{
recipients: {
$all: [
{ $elemMatch: { $eq: patientId }},
{ $elemMatch: { $eq: doctorId }}
],
}
}
)
if (conversationBetween) {
return res.status(401).json({
status: "failed",
message: "You already have a conversation with this doctor"
});
}
following Code to add a Conversation in the Conversation Collection, this works fine
const newConversation = new Conversation({
recipients: [ patientId,doctorId ],
lastMessage: `I want to get consultation`,
date: Date.now(),
})
await newConversation.save()
res.status(200).json({
status: "success",
message: "Conversation added successfully",
conversation: newConversation
});
The main purpose is to make sure that if there present an entry with [ patientId, doctorId ] in Conversation it should not make a new entry..
But at this time its not able to find and is making that same entry.
You can do this
await Conversation.findOne(
{
recipients: [patientId, doctorId]
}
)
Working in Playground
I am following the docs without luck and am at a standstill while trying to update an object in an object in an array using MongoDB and Mongoose.
Here is my document:
{
fields: [
{ id: 603d63086db2db00ab09f50f, data: [Object] },
{ id: 603d63086db2db00ab09f510, data: [Object] },
{ id: 603d63086db2db00ab09f511, data: [Object] },
{ id: 603d63086db2db00ab09f512, data: [Object] },
{ id: 603d63086db2db00ab09f513, data: [Object] },
{ id: 603d63086db2db00ab09f514, data: [Object] },
{ id: 603d63086db2db00ab09f515, data: [Object] }
],
layouts: [],
_id: 603d631a6db2db00ab09f517,
bandId: '603d63146db2db00ab09f516',
eventType: 'private',
ownerId: '6039354906410800c14934c1',
__v: 0
}
I am trying to updateOne of the fields.data in the fields array. fields.data is an object as well.
I call my Express/Node Backend to this route.
//Update
router.put("/:id", async (req, res) => {
try {
let updating = await QuoteGenerator.updateOne(
{ _id: req.params.id, "fields.id": req.body.id },
{
"$set": {
"fields.$.data": req.body.data,
},
}
);
let item = await QuoteGenerator.findOne({ _id: req.params.id });
res.json({ success: "Item Updated.", item });
} catch (err) {
console.log(err);
res.json({ error: "Something went wrong when updating this item." });
}
});
Where req.body is:
{ id: '603d63086db2db00ab09f50f', data: { type: 1, rate: '200.30' } }
**Just in case it's helpful, here is what one of the fields objects looks like in the document,
{"id":"603d63086db2db00ab09f50f","data":{"type":1,"rate":300}}
I have even tried changing my route to find this document - which I have confirmed exists - Truly at a loss why it won't find the document.
Here is how I changed the above route to find the document.
//Update
router.put("/:id", async (req, res) => {
try {
let updating = await QuoteGenerator.find(
{ _id: req.params.id, "fields.id": req.body.id },
);
console.log(updating) //returns []
let item = await QuoteGenerator.findOne({ _id: req.params.id });
res.json({ success: "Item Updated.", item });
} catch (err) {
console.log(err);
res.json({ error: "Something went wrong when updating this item." });
}
});
The Model
//Create Schema - QG
const QuoteGeneratorSchema = new Schema({
bandId: {
type: String,
required: true,
},
ownerId: {
type: String,
required: true,
},
fields: {
type: Array,
default: defaultFields,
required: true,
},
eventType: {
type: String,
required: false,
},
layouts: {
type: Array,
required: false,
},
});
let QuoteGenerator = mongoose.model("QuoteGenerator", QuoteGeneratorSchema);
module.exports = QuoteGenerator;
Any nudge in the right direction to replacing that data object with a new data object would be extremely helpful! Thanks!
I am following a full-stack web development guide. The git repository can be found here:
https://github.com/cliveharber/gettingMean-2/tree/chapter-06
In chapter 6, I've created an API that is supposed to display a list of locations based on the GPS coordinates. When I test the get request I get an empty array. The get request URL is:
http://localhost:3000/api/locations?lat=51.455041&lng=-0.9690884
This is the controller code for locations:
Note that I use a Mongoose aggregate called $geonear to find a list of locations close to a specified point
const locationsListByDistance = async (req, res) => {
const lng = parseFloat(req.query.lng);
const lat = parseFloat(req.query.lat);
const near = {
type: "Point",
coordinates: [lng, lat]
};
const geoOptions = {
distanceField: "distance.calculated",
key: 'coords',
spherical: true,
maxDistance: 20000
};
if (!lng || !lat) {
return res
.status(404)
.json({ "message": "lng and lat query parameters are required" });
}
try {
const results = await Loc.aggregate([
{
$geoNear: {
near,
...geoOptions
}
}
]);
const locations = results.map(result => {
return {
id: result._id,
name: result.name,
address: result.address,
rating: result.rating,
facilities: result.facilities,
distance: `${result.distance.calculated.toFixed()}m`
}
});
res
.status(200)
.json(locations);
} catch (err) {
res
.status(404)
.json(err);
}
};
This is my location model:
const locationSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
address: String,
rating: {
type: Number,
'default': 0,
min: 0,
max: 5
},
facilities: [String],
coords: {
type: {type: String},
coordinates: [Number]
},
openingTimes: [openingTimesSchema],
reviews: [reviewSchema]
});
I am sure I use the right GPS coordinates in the get request URL. This the document I am trying to retrieve from the database:
I am not sure why I'm getting an empty array when testing this API. Are there any issues in my code?
If I'm reading your code right, the aggregation that you are sending is:
Loc.aggregate([
{
$geoNear: {
{
type: "Point",
coordinates: [lng, lat]
},
distanceField: "distance.calculated",
key: 'coords',
spherical: true,
maxDistance: 20000
}
}
]);
You haven't mentioned creating a 2dsphere index on the coords field of the collection, I'll assume you have done that.
That aggregation seems to be missing the near field name, like:
Loc.aggregate([
{
$geoNear: {
near: {
type: "Point",
coordinates: [lng, lat]
},
distanceField: "distance.calculated",
key: 'coords',
spherical: true,
maxDistance: 20000
}
}
]);
I try to add an geojson object to an existing array in mongodb, this is my object that I'd like to add:
const location = {
type: "Feature",
properties: {
description: place.address,
name: place.name
},
geometry: {
coordinates: [
place.latLng.latitude,
place.latLng.longitude
],
type: "Point"
},
userIds: [userId],
id: place.id
}
I tried using this mongodb call without any effect:
db.collection.updateOne(
{ _id: "5e6e32051c9d4400128cba9c" },
{ $push: { features: location } },
function(err, result) {
if (err) {
reject(err);
}
console.log(result);
console.log("Added new location successfully");
resolve(true);
});
This does nothing. Features is an array which should contain geojson objects.
What do I do wrong?
Ok, I found the answer on this page: https://www.quora.com/How-do-I-update-a-document-in-mongodb-using-_id-as-query-parameter
In order to query for an _id you apparently have to convert the _id into an ObjectId first.
So I did this here:
const ObjectID = require('mongodb').ObjectID;
const id = ObjectID("5e6e32051c9d4400128cba9c");
And then:
db.collection.updateOne(
{ _id: id },
{ $push: { features: location } },
function(err, result) {
if (err) {
reject(err);
}
console.log(result);
console.log("Added new location successfully");
resolve(true);
});
This did work! :)
I try to create valid geojson FeatureCollection and some problems occurred during updating document in collection.
My Model
var mongoose = require('mongoose');
Schema = mongoose.Schema;
var DataSchema = new Schema({
type: {type:String, default:"Feature"},
properties:{
title: { type: String, required: true },
description: { type: String, required: true},
date: {type:Date, default:Date.now}},
geometry:{
type:{type:String, default:"Point"},
coordinates: {type: [Number]}}
});
var MetadataSchema = new mongoose.Schema({
type : {type: String, default: "FeatureCollection"},
features: [DataSchema]
});
var rescueModel = mongoose.model('rescueModel', MetadataSchema);
Router
router.post('/mountain_rescue', function(req, res){
db.collection('rescuemodels', function(err, collection){
collection.update({
"type": "FeatureCollection"
},
{
$push: {
"features": {
properties: {
title: req.body.title,
description: req.body.description
},
geometry: {
coordinates: req.body.coordinates.split(',')
}
}
}
});
res.redirect('/mountain_rescue');
});
});
module.exports=rescueModel;
So If everything is okay but why is it that after executing post route I get
TypeError: Cannot call method 'update' of undefined
I also checked the command in mongo shell and it works
db.rescuemodels.update(
{
"type":"FeatureCollection"
},
{
$push:{
"features": {
"properties":{"title":"WOW"}
}
}
}
)
The problem is that collection is not defined before running the update. Also, you might want to do the redirect in the callback to the update function, but that will depend on the behaviour you are looking for. Your code would then look something like this:
var collection = db.collection('rescuemodels');
collection.update({
"type": "FeatureCollection"
},
{
"$push": {
"features": {
"properties": {
"title": req.body.title,
"description": req.body.description
},
"geometry": {
"coordinates": req.body.coordinates.split(',')
}
}
}
}, function(err, result) {
if (err) throw err;
res.redirect('/mountain_rescue');
});