findOneAndUpdate for a 2dsphere - mongodb

const sessionId = uuid.v4();
//Session.
io.on("connection", (socket) => {
socket.on("locationData", async (data) => {
const latitude = data.latitude;
const longitude = data.longitude;
Session.findOneAndUpdate(
{ sessionId: sessionId },
{
$set: {
location: { coordinates: [longitude, latitude] },
speed: data.speed,
},
},
{ upsert: true, new: true },
(err) => {
if (err) {
console.error(err);
return;
}
console.log("Data inserted/updated");
}
);
console.log(data);
});
});
im trying to get realtime location data with socket io and put it in my DB, it was working perfect till i realised i need to add index:"2dsphere" to the coords, apparently the findOneAndUpdate doesnt work with a geospatial point. what should i use in this case please
const sessionId = uuid.v4();
//Session.
io.on("connection", (socket) => {
socket.on("locationData", async (data) => {
const latitude = data.latitude;
const longitude = data.longitude;
Session.findOneAndUpdate(
{ sessionId: sessionId },
{
$set: {
location: { coordinates: [longitude, latitude] },
speed: data.speed,
},
},
{ upsert: true, new: true },
(err) => {
if (err) {
console.error(err);
return;
}
console.log("Data inserted/updated");
}
);
console.log(data);
});
});

It worked by modifying my code:
location: {
type: "Point",
coordinates: [longitude, latitude],
},

Related

Aggregate method for each document resulting from find method in mongodb

I want to execute this aggregate query:
db.collection('mycoll').aggregate([
{
$search: {
index: 'default',
text: {
query: 'night',
path: {
wildcard: '*',
},
},
},
},
])
})
for each document resulting from my find method:
here is my find method:
app.get('/', (req, res) => {
db.collection('subs').find(
{ name: { $regex: 'dexter', $options: '$i' } },
{ projection: { _id: 0, content: 0 } }
)
.toArray((err, result) => {
if (err) {
throw new err();
}
res.json({
length: result.length,
body: { result },
});
});
});
I know I probably have to use forEach and create a function, but I couldn't find out what to put in this function, I assume ## Heading ##it should be something like that:
.find(
{ name: { $regex: 'dexter', $options: '$i' } },
{ projection: { _id: 0, content: 0 } }
).forEach(()=>{})
.toArray((err, result) => {
if (err) {
throw new err();
}
res.json({
length: result.length,
body: { result },
});
});
});
You can achieve this in several different ways, here is the simplest code sample I could produce:
app.get('/', async (req, res) => {
const result = await db.collection('subs').find(
{name: {$regex: 'dexter', $options: '$i'}},
{projection: {_id: 0, content: 0}}
).toArray();
const finalResults = await Promise.all(result.map(async (each) => {
each.textSearchResults = await db.collection('mycoll').aggregate([
{
$search: {
index: 'default',
text: { // decide what your query is based on each document
query: each.name,
path: {
wildcard: '*',
},
},
},
},
])
return each
}))
res.json({
length: result.length,
body: {result},
});
});

Updating array of objects in Mongoose

I can't handle updating array of objects in my database, tried many options but nothing worked. Im pretty sure that the answer is obvious, but I couldn't manage it since wednesday.
Here is my kitSchema:
const kitSchema = new mongoose.Schema({
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
kit: {
type: Array,
required: true,
},
profiles: {
type: Array,
required: true,
},
});
module.exports = mongoose.model("Kit", kitSchema);
All users have their own document, and there are also profiles in it. I want to update single profile by passing the id of user and id of profile.
Example of data:
_id: 1,
email: "abc#mail",
password: "abc",
profiles: [
{
id: 1,
name: John
},
]
And here's my latest solution which doesn't work:
router.put("/profile/:id", async (req, res) => {
let kit = await Kit.findById(req.params.id, (error, data) => {
if (error) {
console.log(error);
} else {
console.log(data);
}
});
try {
await kit.profiles.findOneAndUpdate(
{ id: req.body.id },
{ name: req.body.name },
{ new: true },
(error, data) => {
if (error) {
console.log(error);
} else {
console.log(data);
}
}
);
try {
res.status(202).json({ message: "Changed" });
} catch (err) {
res.status(400).json({ message: err });
}
} catch (err) {
res.status(400).json({ message: err });
}
});
Could you give me a hand with this?
As always, after days of trying I've got answer 10 minutes after asking question. Here's what I came up with:
router.put("/profile/:id", async (req, res) => {
await Kit.findOneAndUpdate(
{ _id: req.params.id, profiles: { $elemMatch: { id: req.body.id } } },
{
$set: {
"profiles.$.name": req.body.name,
"profiles.$.profilePicture": req.body.profilePicture,
},
},
{ new: true, safe: true, upsert: true },
(error, data) => {
if (error) {
console.log(error);
} else {
console.log(data);
}
}
);
try {
res.status(202).json({ message: "Changed" });
} catch (err) {
res.status(400).json({ message: err });
}
});

findByIdAndUpdate do not update document

I am trying to update a field to the document with findByIdAndUpdate. The field I am trying to update is defined in the Bar Model. And I can also assure that req.body.bookId has a valid id.
Here's how my request looks,
app.patch("/foo", async (req, res) => {
try {
await validateId(req.body.bookId);
let doc = await Bar.findByIdAndUpdate(
req.body.bookId,
{ DateT: Date.now() },
{ new: true }
);
res.send(doc);
} catch (err) {
console.log(err);
}
});
Bar schema,
const mongoose = require("mongoose");
const barSchema = mongoose.Schema({
bookId: {
type: String,
unique: true,
},
DateT: {
type: Date,
default: null,
},
});
module.exports = mongoose.model("Bar", barSchema);
use updateOne, when you use async don't use .then() use try/catch
test it:
app.patch("/foo", async (req, res) => {
try {
let doc = await Bar.updateOne(
{ bookId : req.body.bookId },
{ DateT: Date.now() },
{ new: true }
);
res.send(doc);
} catch (error) {
console.log(error);
}
});
app.patch("/foo", async (req, res) => {
await Bar.findByIdAndUpdate(
req.body.bookId,
{ DateT: Date.now()},
(err, docs) => {
if (err) {
console.log(err);
} else {
res.send(docs);
}
}
);
});

Mongodb timestamps for querying documents

I want to fetch all the documents created on D-1 day, i.e. suppose if any record has been created on 4-12-2019 then query should fetch records created on 3-12-2019.
Here is my Model and code:
VENDOR ORDER SCHEMA
const vendorOrderSchema = new mongoose.Schema({
timesOfIndia:{
tradeCopies:{
type:Number,
deafult:0 },
subscriptionCopies:{
type:Number,}
},
economicTimes:{
tradeCopies:{
type:Number,
deafult:0
},
subscriptionCopies:{
type:Number,}
},
mumbaiMirror:{
tradeCopies:{
type:Number,
deafult:0
},
subscriptionCopies:{
type:Number}
},
isApproved:{
type:Boolean,
default:false
},
vOrderCreator:
{
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required:true
}
},
{ timestamps: true }
)
const VendorOrder = mongoose.model('VendorOrder',vendorOrderSchema)
module.exports = VendorOrder
Query:
exports.getOrderById = async (req,res,next) =>{
const vOrderCreator = req.params.id
const vendorOrder = await VendorOrder.find({vOrderCreator,
createdAt: { $gt: new Date(Date.now() - (1000 * 60 * 60 * 24)) }
})
try {
if (!vendorOrder) {
const error = new Error('Could not find post.');
error.statusCode = 404;
throw error;
}
res.status(200).json({ message: 'VendorOrder fetched.', vendorOrder });
} catch (err) {
if (!err.statusCode) {
err.statusCode = 500;
}
next(err);
}}
POSTMAN RESPONSE
{
"message": "VendorOrder fetched.",
"vendorOrder": [] // getting this empty array
}

How to define a circle using GeoJson?

I want to use geometry in Mongodb.
But circle is not supported in geojson according to the geojson.org
I had exactly the same problem, the solution is to create a polygon that roughly approximates a circle (imagine a polygon with 32+ edges).
I wrote a module that does this. You can use it like this:
const circleToPolygon = require('circle-to-polygon');
const coordinates = [-27.4575887, -58.99029]; //[lon, lat]
const radius = 100; // in meters
const numberOfEdges = 32; //optional that defaults to 32
let polygon = circleToPolygon(coordinates, radius, numberOfEdges);
You will need to model it as a point and then store the radius in another field. If you want to test whether or not something is inside of that circle, you will need to use the proximity spatial index as discussed here
{
<location field>: {
$geoWithin: { $centerSphere: [ [ <x>, <y> ], <radius> ] }
}
}
https://docs.mongodb.com/manual/reference/operator/query/centerSphere/
Since v1.8
Another approach to it. In this case, I have used mongoose one of the most popular distribution of MongoDB to add a circle to a map with a radius and then query using an external parameter and assessing if it's inside a circle or outside the circle.
This example also has commented section for polygon, where if you have saved a polygon and you want to search if the point exists inside a polygon, you can do that too. Also, there is an upcoming section for a full integration of front end and backend for a complete geofence experience.
The code
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var assert = require('assert');
console.log('\n===========');
console.log(' mongoose version: %s', mongoose.version);
console.log('========\n\n');
var dbname = 'testing_geojsonPoint';
mongoose.connect('localhost', dbname);
mongoose.connection.on('error', function() {
console.error('connection error', arguments);
});
// schema
var schema = new Schema({
loc: {
type: {
type: String
},
coordinates: []
},
radius : {
type : 'Number'
}
});
schema.index({
loc: '2dsphere'
});
var A = mongoose.model('A', schema);
// mongoose.connection.on('open', function() {
// A.on('index', function(err) {
// if (err) return done(err);
// A.create({
// loc: {
// type: 'Polygon',
// coordinates: [
// [
// [77.69866, 13.025621],
// [77.69822, 13.024999, ],
// [77.699314, 13.025025, ],
// [77.69866, 13.025621]
// ]
// ]
// }
// }, function(err) {
// if (err) return done(err);
// A.find({
// loc: {
// $geoIntersects: {
// $geometry: {
// type: 'Point',
// coordinates: [77.69979,13.02593]
// }
// }
// }
// }, function(err, docs) {
// if (err) return done(err);
// console.log(docs);
// done();
// });
// });
// });
// });
mongoose.connection.on('open', function() {
A.on('index', function(err) {
if (err) return done(err);
A.create({
loc: {
type: 'Point',
coordinates: [77.698027,13.025292],
},
radius : 115.1735664276843
}, function(err, docs) {
if (err) return done(err);
A.find({
loc: {
$geoNear: {
$geometry: {
type: 'Point',
coordinates: [77.69735,13.02489]
},
$maxDistance :docs.radius
}
}
}, function(err, docs) {
if (err) return done(err);
console.log(docs);
done();
});
});
});
});
function done(err) {
if (err) console.error(err.stack);
mongoose.connection.db.dropDatabase(function() {
mongoose.connection.close();
});
}
See full example in action