How to use MongoDB Subdocument _id with EJS - node.js

I'm trying to get a subdocument from MongoDB using Mongoose, then pass the data to an EJS doc but I'm getting an Uncaught SyntaxError: Invalid or unexpected token because of the _id object. Ideally I would like the _id to be a string, but using toString() or toHexString() doesn't work.
Here are my basic Schemas:
var hikeSessionSchema = new mongoose.Schema({
hike_name: {type: String, required: true},
hike_date: {type: String, required: true},
mileage: {type: Number, required: true}
})
var hikerSchema = new mongoose.Schema({
username: {type: String, required: true},
log: [hikeSessionSchema]
})
var HikeSession = mongoose.model('HikeSession', hikeSessionSchema)
var Hiker = mongoose.model('Hiker', hikerSchema)
And here's my GET request:
app.set('view engine', 'ejs');
...
app.get('/users/:id/:hike', (req, res) => {
var id = req.params.id;
var hikeId = req.params.hike;
Hiker.findById(id, (err, hiker) => {
const hike = hiker.log.id(hikeId)
console.log(hike)
res.render('editHike', { data: hike })
})
When I console.log(hike) I get:
{
_id: 6125629447cec024c067c1da,
hike_name: 'Hike Name',
hike_date: '2021-08-04',
mileage: 10
}
I've tried saving the _id to a variable as a string, then replacing the _id with the variable, but it goes back to an object. I've also tried delete hike._id but that doesn't work either.
I need to be able to be able to reference the _id in the EJS doc for later use. Maybe there's a way to get the HikeSession object without the _id and then save the _id separately? How can I make this work? Thanks

I came up with a workaround by duplicating the object without the _id field, making a variable for turning _id into a string, then adding that variable to the new object.
app.get('/users/:id/:hike', (req, res) => {
var id = req.params.id;
var hikeId = req.params.hike;
Hiker.findById(id, (err, hiker) => {
var hikeData = hiker.log.id(hikeId)
var hike = (({ hike_name, hike_date, mileage }) => ({ hike_name, hike_date, mileage }))(hikeData);
var idStr = hikeData._id.toString()
hike.id = idStr;
res.render('editHike', { data: hike })
})
Then importing in the EJS file like this:
var data = <%- JSON.stringify(data) %>;
There's probably a better way to do it, but this worked.

Related

empty result when getting data from mongodb with mongoose and node js

I'm trying to fetch all my documents from a collection in my MongoDb DB but I can't do it. I have absolutely no error but it just returns an empty array in my console.
Model :
import mongoose from "mongoose";
const websiteSchema = mongoose.Schema({
id: {type: String},
name: {type: String, required: true},
url: {type: String, required: true},
note: {type: Number, required: true}
});
export default mongoose.model("Website", websiteSchema);
File in which I want to use the data :
import express from 'express';
import Website from '../models/website.js';
const routerWebsiteList = express.Router();
routerWebsiteList.get('/website-list', async function(req, res, next) {
try {
const websitesToCrawl = await Website.find({});
console.log(websitesToCrawl);
} catch (error) {
res.status(500).json({message : "An error occured"});
}
})
export default routerWebsiteList;
All I get in my console is [].
My data in my database seems good too :
Accully everything looking fine maybe you can use
require for import files
const name = require('name')
and for the export file :
module.exports = routerWebsiteList
after that be sure you connected your database correct like this
async function database() {
await mongoose
.connect(process.env.DATABASE_URL)
.then(() => {
console.log("Database Coonected");
})
.catch((err) => {
console.log(err);
});
}
database()
Last detail is you don't need to put id on mongoose schema just remove it and finally change your model like this
const mongoose = require("mongoose");
const websiteSchema = mongoose.Schema({
name: {type: String, required: true},
url: {type: String, required: true},
note: {type: Number, required: true}
});
const Website = mongoose.model("Website", websiteSchema);
module.exports = Website
I hope that will be helpful. If you will be stuck somewhere feel free to type here again.
I finally found what was the problem. The mongoose Schema was looking in a wrong collection named "websites". All I had to do was to specified the collection name in my model as following : ("websitesToCrawl" is the collection name)
export default mongoose.model("Website", websiteSchema, "websitesToCrawl");

How do I use MongoDB data with D3 and Node?

Using Node, Express, Mongoose, and MongoDB, I'm trying to send a GET request to MongoDB and then use the data as an object for a D3 graph. I have the code for the graph in a separate js file. How do I send the data to that file?
Here are the basic Schemas I'm using:
var hikeSessionSchema = new mongoose.Schema({
hike_name: {type: String, required: true},
hike_date: {type: String, required: true},
mileage: {type: Number, required: true},
duration: {type: String, required: true},
elevation_gain: {type: Number, required: true},
city: {type: String, required: true},
location: {type: String, required: true},
notes: String
})
var hikerSchema = new mongoose.Schema({
username: {type: String, required: true},
log: [hikeSessionSchema]
})
var HikeSession = mongoose.model('HikeSession', hikeSessionSchema)
var Hiker = mongoose.model('Hiker', hikerSchema)
So I want to find the user by ID, then get an array of the user's HikeSessions. And I want to move that data to a js doc to make a d3 graph (I've already made the d3 app on CodePen but connected it to Google Sheets before).
I think the GET request should be something like this, but I don't know what to do with the result. The path will probably change:
app.get('/:id', (req, res) => {
const id = req.params.id;
Hiker.findById(id)
.then(result => {
//What goes here?
})
.catch(err => {
console.log(err);
})
}
After I get the data into the d3 doc, I'm not sure what challenges I'll run into with rendering it.
Step 1:
Define and export your d3_generator(input) function in d3.js:
const d3_generator = (input) => {
/// (Your logic)
}
module.exports = { d3_generator };
Step 2
Import d3_generator function from d3.js in your controller and use it after you got result from MongoDB:
const { d3_generator } = require('./d3');
...
app.get('/:id', (req, res) => {
const id = req.params.id;
Hiker.findById(id)
.then(result => {
let generated_d3 = d3_generator(result.log);
})
.catch(err => {
console.log(err);
})
}

Geting empty array when find with some criteria in mongoose

Schema :
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Config = require('../Config');
var serviceAvailability = new Schema({
agentId: {type: Schema.ObjectId, ref: 'agentProfile', required: true},
availabilityDate: {type: Date, required: true},
availabilityTime: {type: Array, required: true}
});
serviceAvailability.index({agentId:1 , availabilityDate:1},{unique:true});
module.exports = mongoose.model('serviceAvailability', serviceAvailability);
Controller :
Models.serviceAvailability.find({'agentId':'abcd'}, function (err, service) {
console.log(service);
if(service) {
callback(err , service);
}
else {
callback(err);
}
});
I am trying to get all data with some criteria like if agentId is equal to some value but whenever i am using any criteria to find data i am getting empty array while if i remove the criteria and find all data then i am getting data, why is this ?
I think, you try to find a mongoDB document with a request on ObjectId Field, but, in your example, you don't use a correct ObjectId String Value.
ObjectId is a 12-byte BSON type, constructed using:
So, this is a correct way to request your serviceAbility with a correct ObjectId :
Models.serviceAvailability.find({
'agentId':'507f1f77bcf86cd799439011'
}, function (err, service) {
if (err) {
callback(err);
return;
}
callback(null, service);
});
In this case, you should have an agentProfile with the _id equals to 507f1f77bcf86cd799439011

Using a value of an document as _id when importing this document to MongoDB using NodeJS

I'm trying to import an Object into Mongo. But when I try to use a value of the Object as _id it fails. The error i.e: "[CastError: Cast to ObjectID failed for value "11563195" at path "_id"]" and later "[Error: document must have an _id before saving]"
What am I doing wrong ?
// Read and import the CSV file.
csv.fromPath(filePath, {
objectMode: true,
headers: keys
})
.on('data', function (data) {
setTimeout(function(){
var Obj = new models[fileName](data);
Obj._id = Obj.SOME_ID;
Obj.save(function (err, importedObj) {
if (err) {
console.log(err);
} else {
console.log('Import: OK');
}
});
}, 500);
})
Here is the used Schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var SomeSchema = new Schema(
{
SOME_ID: String,
FIELD01: String,
FIELD02: String,
FIELD03: String,
FIELD04: String,
FIELD05: String,
FIELD06: String,
FIELD07: String,
FIELD08: String,
FIELD09: String,
FIELD10: String,
FIELD11: String,
FIELD12: String,
FIELD13: String
},
{
collection: 'SomeCollection'
});
module.exports = mongoose.model('SomeCollection', SomeSchema);
Many thanks for your time and help.
By default mongoose is validating that the _id field is a MongoId. If you want to store something other than a MongoId in the _id field you will need to give the _id field a different type.
var SomeSchema = new Schema({
_id: { type: String, required: true }
}

Nodejs, Mongoose and Jade get no data from Database

i was searching for my Problem but even don't know where is the problem.
I get the title which is set in my route but no data from the database...
My model:
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
ObjectId = Schema.Types.ObjectId;
var blogSchema = new Schema({
title: { type: String, required: true },
author: { type: String, required: true },
body: { type: String, required: true },
date: { type: String, required: true },
hidden: Boolean
});
module.exports = mongoose.model('Blog', blogSchema);
my router:
var express = require('express'),
Blog = require('../models/blog'),
moment = require('moment');
moment.lang('de');
var router = express.Router();
router.get('/articles', function(req, res) {
Blog.find(function(err, docs){
return res.render('blog/articles', {
title: 'Blog_',
articles: docs
});
});
});
app.use('/blog', router);
my jade
extends ../layouts/default
include ../elements/form-elements
block content
h1= title
each article in articles
.col-md-12
div.title= article.title
the only one i get displayed at the Page is
Blog_
So what iam doing wrong?
At the error file it only says:"Cannot read property 'title' of undefined"
So the articles objects are not set...but why?
Thanks so much
edit 1:
change article.title to article doesn't change anything
in the log files is
GET /blog/articles HTTP/1.1 304 - - 3 ms
edit 2:
it seems that node doesnt get any data from the db...
and yes there is one testdata set ;)
console.log() ->
err: null
docs: []
Solution is posted as answer
got the solution...
the model wasn't right...
var blogSchema = new Schema({
title: { type: String, required: true },
author: { type: String, required: true },
body: { type: String, required: true },
date: { type: String, required: true },
hidden: Boolean
}, {collection : 'blog'});
have to name the collection at the end...cause its written in small letters -.-
What a false - never ever do it again ^^
I know this is a very old question and it's marked by OP as answered, but I think the real problem was in "my router", you're not referencing your "docs" (the data coming back from the database) correctly. Keep in mind "docs" is an array so you would need to reference them like this:
router.get('/articles', function(req, res) {
Blog.find(function(err, docs){
return res.render('blog/articles', {
title: docs[0].title, // Get the title for first entry
articles: docs[0].body // Get body for the first entry
});
});
});
I'm hardcoding the array index but you can use a loop to get every item from the array.
I don't think OPs solution fixes the problem because...
By default, when compiling models with:
const someModel = mongoose.model('someModel', SomeSchema);
mongoose creates a collection using 'someModel' name and adding an "s" at the end, so if you check your database, your collection should
appear as 'someModels'. With OP's solution:
{ collection: 'blog' }
as the second parameter when creating the blog schema
var blogSchema = new Schema();
That default behavior is overwritten and the name of your collection will be whatever you set as the value for collection, in this case, "blog".
You can read more about it in Mongoose official docs
or in the Models section in MDN - Node/Express/Mongoose

Resources