I have the following codes which try to create secondary indexes with mongoose. I have followed the mongoose official document to implement it ( mongoose documentation: Indexes section). However, when I send a GET request through Postman, an error, "unable to find index for $geoNear query", occurs. My understanding is that in my case, location is equivalent to a $geoNear object, so my code should be fine (I know it's not fine. That's why I have got an error). Any comments or suggestions would be greatly appreciated.
app.js(get endpoint)
app.get('/api/stores', (req, res) => {
const zipCode = req.query.zip_code;
const googleMapsURL = "https://maps.googleapis.com/maps/api/geocode/json";
axios.get(googleMapsURL, {
params: {
address: zipCode,
key : "KEY"
}
}).then((response) => {
const data = response.data
const coordinates = [
data.results[0].geometry.location.lng,
data.results[0].geometry.location.lat,
]
Store.find({
location: {
$near: {
$maxDistance: 3218,
$geometry: {
type: "Point",
coordinates: coordinates
}
}
}
}, (err, stores)=> {
if (err) {
console.log(err);
res.status(500).send(err);
} else {
res.status(200).send(stores);
}
})
}).catch((error)=> {
console.log(error);
})
})
store.js
const mongoose = require('mongoose');
const storeSchema = mongoose.Schema({
storeName: String,
phoneNumber: String,
address: {},
openStatusText: String,
addressLines: Array,
location: {
type: {
type: String,
enum: ['Point'],
required: true
},
coordinates: {
type: [Number],
required: true
}
}
})
storeSchema.index({ location : "2dsphere"}, {sparse: true});
module.exports = mongoose.model('Store', storeSchema);
When creating a new index in MongoDB, you may have to drop the table as to have the index apply properly. Try creating the index on a fresh table. Does that work?
I figured out this error by first creating a new database and collection(I was using the default database named <dbname>). When I sent a POST request with the data I would like to store in MongoDB, MongoError: Can't extract geo keys appeared. I fixed this error by following this thread(reference). After these steps, my GET request worked and indexes were successfully created.
Related
So my knowledge of NodeJS and MongoDD are non-existent (just need to do a small code update for a friend) and I'm stuck.
Need to update a single document inside a collection via a unique id but can't seem to do it.
Here's the Model (I've trimmed it down and cut out all unnecessary data). I'm trying to update the field notes inside a transaction.
In short each entry in the given (an Agent) table will have a collection of multiple Transactions & Documents. I need to update a specific Transaction with the unique _id that is auto generated.
import { Schema, model } from 'mongoose';
interface Transaction {
first_name: string;
last_name: string;
type: string;
notes: string;
}
interface Agent {
org_id: number;
transactions: Array<Transaction>;
documents: Array<string>;
}
const transactionSchema = new Schema<Transaction>({
first_name: { type: String },
last_name: { type: String },
type: { type: String },
notes: String,
});
const transactionsSchema = new Schema<Agent>({
org_id: { type: Number },
transactions: [transactionSchema],
documents: [documentTypesSchema],
});
const AgentTransaction = model<Agent>(
'agent_transaction_table',
transactionsSchema
);
export default AgentTransaction;
Here's what I tried but didn't work (obviously), again I've trimmed out all unnecessary data. Just to clarify, the endpoint itself works, but the DB update does not.
import AgentTransaction from '../models/transaction'; // the above model
transaction.put('/notes', async (req, res) => {
const { org_id, transaction_id, notes } = req.body;
try {
const notesResult = await AgentTransaction.updateOne({
'transactions._id': transaction_id,
}, {
$set: {
'notes': notes
},
});
res
.status(200)
.json({ message: 'Updated', success: true, notesResult });
} catch (error) {
res.status(400).send(error);
}
});
So I figured it out. Maybe it'll help someone else as well.
const notesResult = await AgentTransaction.updateOne({
'transactions._id': { $in: [trunc2] },
}, {
$set: {
'transactions.$.notes': notes
},
});
The main issue was that the payload object needed to target the collection folder + the wildcard + the field, not just only the field.
I'm setting up a simple blog form with title, content, and json base64 image data to pass to a local MongoDB server. This is my post route:
router.post('/:userName/posts/new', isAuthenticated, async (req, res) => {
let parsedImage = req.body.file != null && req.body.file != '' ? JSON.parse(req.body.file).data : ''
const newPost = new Post({
title: req.body.title,
content: req.body.content,
imageJson: parsedImage
})
try {
await newPost.save()
res.redirect("/account")
} catch (e) {
console.log(e)
res.redirect("/home")
}
})
And this is my schema model:
const mongoose = require('mongoose');
const postSchema = new mongoose.Schema({
title: {
type: String,
required: true,
},
content: {
type: String,
required: true,
},
imageJson: {
type: String
}
});
module.exports = mongoose.model('Post', postSchema)
no unique: true as you can see. The first time I tried running this, it ran perfectly, redirecting directly to the /account page, as intended in the try catch block. But, on a second attempt, using a different image, different content, and different title, it threw this error:
MongoError: E11000 duplicate key error collection: fullstacksus.posts index: userName_1 dup key: { userName: null }
I have no idea what's going on since userName is a database name used in my user account route, but not in my post-making route. Why is it showing up again? Thanks for your answers.
In your MongoDB there is a unique index on {userName: 1}. Since your schema does not have a userName field, it is missing, i.e. null, in every document, so the index rejects it.
Use the mongo shell to connect and drop the index.
I am using mongoose along with nodejs to insert data. I am using MVC and in my controller I have this code:
module.exports.create_tracsaction = function (req, res) {
Company.findOne({ username: req.body.req_from }, function (err, user) {
if (user.vaccine.extra < req.body.req_vac) {
return res.redirect('/vaccine');
}
else {
var data = {
req_from: req.body.req_from,
req_to: req.body.req_to,
amt_req: req.body.req_vac,
transaction_status: "Awaiting confirmation",
vaccine: user.vaccine.name,
transaction_value: user.vaccine.price * req.body.req_vac
}
Transaction.create(data);
return res.redirect('/vaccine');
}
})
console.log(req.body);
};
This is my schema
const transactionSchema = new mongoose.Schema({
req_from: {
type: String,
required: true
},
req_to: {
type: String,
required: true
},
amt_req: {
type: Number,
required:true
},
transaction_status: {
type: String,
default: "Awaiting confirmation"
},
vaccine: String,
transaction_value: Number
}, {
timestamps: true
});
Even though non of the fields have property unique:'true', I am getting this error:
MongoError: E11000 duplicate key error collection: innovate_dev.transactions index: username_1 dup key: { username: null }
How to remove this error? The first time I sent data from views there was no error but from thereafter it's giving this error every time.
Let me know if you need anything else. Thanks in advance :D
It looks like a unique index got created at some point on the username field of transactions. That according your schema, it no longer exists. Thus every time you make an entry null is being indexed and throwing an error.
If you are using Compass or another GUI you can go in and delete it.
Otherwise to remove with MongoShell:
use innovate_dev
It will switch to your db
db.transactions.dropIndex('username_1')
I have the following schema to store coordinates:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create Schema
const LocationSchema = new Schema({
// Matches
loc: {
type:
{
type: String
},
coordinates: [Number]
},
member_id: {
type: String
}
});
LocationSchema.index({ loc: '2dsphere' });
mongoose.model('locations', LocationSchema);
I have also created a get route to get to the page where I want to show this stored coordinates data. When I hit the route I get the following in the console.log which I am using to debug:
{ loc: { coordinates: [ 74.360106, 31.497754 ], type: 'Point' },
_id: 5b5abd4bdcbd0f4e5c70b799,
member_id: 'HyQUa4_N7',
__v: 0 }
This looks fine to me since I am getting back the coordinates and the member ID. Following is the code for my get route using which I am passing the data to my express handlebars view:
// Manage Location
router.get('/userlocation/:member_id', ensureAuthenticated, (req, res) => {
Location.findOne({ member_id: req.params.member_id })
.then(locations => {
console.log(locations);
res.render('users/userlocation', { locations: locations });
})
.catch(error => {
console.log('could not find user location');
});
});
I am confused about how do I show this data in my HTML/View. Normally I use {{variable name}} to show data which is being passed into the view. what format should I use. I tried using {{locations.coordinates[0]}} but that gives me an error.
Please help. This is the first time I am attempting something like this in Node.
You can access the longitude like this:
{{locations.loc.coordinates[0]}}
I would suggest you should define schema like this:
location: {type: [Number], index: '2d'}, // [, ]
I have been working with node.js and mongoose for sometime and I am hitting a wall. I have a database with 20,000 documents and when i search the database from the cli it works fine.
db.Tickets.find({ "Customers.Customer.CustomerID" : '123123123' })
This returns 256 results
Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Define collection and schema for Ticket
var Ticket = new Schema({
UserName: {
type: String
},
Status: {
type: String
},
TicketNumber: {
type: Number
},
Name: {
type: String
},
Description: {
type: String
},
TicketTypeName: {
type: String
},
DueDate: {
type: Date
},
MapCollectDate : {
type: Date
},
NumberofUsersAffected : {
type: Number
},
DNNumber : {
type : String
},
RevisionDate : {
type : Date
},
CommercialImpact : {
type: String
},
Customers :[{
Customer: [{
CustomerID: Number,
CustomerName: String
}]
}],
Although if I test this in node.js using mongoose. I can't get it to return anything
I have a generic search that works
Ticket.find(function (err, tickets){
But can't get the specific search to work.
I am Connecting to Mongo
const config = require('./db');
//const Course = require('./models/Course');
//const CourseRoute = require('./routes/CourseRoute');
const Ticket = require('./models/Ticket');
const TicketRoute = require('./routes/TicketRoute');
const PORT = 4000;
mongoose.connect(config.DB).then(
() => {console.log('Connected to MongoDB') },
err => { console.log('Error connecting to MongoDB' +err)
});
Output of the log
Your node js server is running on PORT: 4000
Connected to MongoDB
Connected to MySQL
My Route End point
router.route('/').get(function (req, res) {
Ticket.find({ "Customers.Customer.CustomerID" : global.auth_username }, function(err, ticket) {
if(err){
console.log(err);
}
else {
res.json(tickets);
}
});
});
Also tried without the variable
router.route('/').get(function (req, res) {
Ticket.find({ "Customers.Customer.CustomerID" : "123123123" }, function(err, ticket) {
if(err){
console.log(err);
}
else {
res.json(tickets);
}
});
});
I had the same issue when I forgot to connect to Mongoose before running query
mongoose.connect(MONGO_URL, mongoOptions)
.then(() => {
// do your thing here
})
You had over a year to figured this out, and I am sure that you did so, but either way it seems that you have a typo in your code. The callback parameter is named ticket - function(err, ticket) {, whereas you are logging tickets - res.json(tickets);. In the generic test you correctly wrote tickets - Ticket.find(function (err, tickets){, which is probably why it worked.
The takeaway lesson here is - use debugging tools instead of logging, makes it easier to catch such problems.
Also, it would be appropriate to answer your own question once you've figured it out. But given that this is probably completely useless, you might as well delete it. Cheers!