I'm new with both of these technologies and really need help.
I have MongoDB set up on my computer and I have mongod running.
I have a database called 'memories-db' & a collection called 'entries', I can run mongosh in a different terminal and am able to get this output from
db.entries.find()
[
{
_id: ObjectId("62e81903809f6ae89c864a4d"),
id: 201901011245,
upvotes: 0,
comments: []
},
{
_id: ObjectId("62e81903809f6ae89c864a4e"),
id: 202001011246,
upvotes: 0,
comments: []
},
{
_id: ObjectId("62e81903809f6ae89c864a4f"),
id: 202201011247,
upvotes: 0,
comments: []
},
{
_id: ObjectId("62e81903809f6ae89c864a50"),
id: 201401011248,
upvotes: 0,
comments: []
}
]
I have an Express server defined as
// Boilerplate
// Import express & its types
import express, { Express, Request, Response } from 'express'
// MongoDB
// Import MongoClient & MongoDB types
import { MongoClient, Db, Collection, WithId, Document } from 'mongodb'
// Constant to store express object
const app: Express = express()
// Constant to store MongoDB URI
const mongoURI: string = 'mongodb://localhost:27017'
// Constant to store port number to listen on
const port: number = 8000
// GET Routes
app.get(
'/api/entries/:entryId',
(req: Request, res: Response) => {
const entryId: number = +req.params.entryId
MongoClient.connect(
mongoURI,
{},
async (error, client) => {
if (error || !client)
res.status(500).json({ message: 'Error connecting to db', error })
else {
const db: Db = client.db('memories-db')
const entryInfo: WithId<Document> | null = await db.collection('entries').findOne({ id: entryId })
res.status(200).json(entryInfo)
client.close()
}
}
)
}
)
app.listen(
port,
() => {
console.log(`⚡️[server]: Server is running at http://localhost:${port}`)
}
)
But when I make GET request I always get an error, please tell me what I'm doing wrong
{
"message": "Error connecting to db",
"error": {
"reason": {
"type": "Unknown",
"servers": {},
"stale": false,
"compatible": true,
"heartbeatFrequencyMS": 10000,
"localThresholdMS": 15
}
}
}
It turns out that my PC wasn't resolving the local MongoDB URI properly.
So, replacing
'mongodb://localhost:27017'
to
'mongodb://127.0.0.1:27017'
fixed the issue
Related
Strapi doesn't have any endpoint to get random data for this purpose you should write some custom code for your endpoint
custom route for that endpoint you want
// path: ./src/api/[your-endpiont]/routes/[custom-route].js
module.exports = {
"routes": [
{
"method": "GET",
"path": "/[your-endpiont]/random", // you can define everything you want for url endpoint
"handler": "[your-endpiont].random", // random is defined as a method
"config": {
"policies": []
}
}
]
}
now you have to run yarn develop or npm ... to display a random method in your strapi panel
Save this setting and retry to reach the random endpoint.
create a function as a service for getting random data in your endpoint API services.
// path: ./src/api/[your-endpiont]/services/[your-endpiont].js
'use strict';
/**
* news-list service.
*/
const { createCoreService } = require('#strapi/strapi').factories;
module.exports = createCoreService('api::news-list.news-list', ({ strapi }) => ({
async serviceGetRandom({ locale, id_nin }) { // these parametrs come from query
function getRandomElementsFromArray(array, numberOfRandomElementsToExtract = 1) {
const elements = [];
function getRandomElement(arr) {
if (elements.length < numberOfRandomElementsToExtract) {
const index = Math.floor(Math.random() * arr.length)
const element = arr.splice(index, 1)[0];
elements.push(element)
return getRandomElement(arr)
} else {
return elements
}
}
return getRandomElement([...array])
}
const newsListArray = await strapi
.db
.query("api::news-list.news-list")
.findMany({
where: {
locale: locale, // if you have multi-language data
$not: {
id: id_nin, // depend on where this endpoint API use
},
publishedAt: {
$notNull: true,
},
},
sort: [{ datetime: 'asc' }],
limit: 10,
populate: {
content: {
populate: {
thumbnail: true,
},
},
},
//? filter object throws an error when you used populate object, everything you want to filter properly best write into where{}
// filters: {
// publishedAt: {
// $notNull: true,
// },
// locale: locale
// }
})
if (!newsListArray.length) {
return null
}
return getRandomElementsFromArray(newsListArray, 2)
}
}));
explain code:
Strapi provides a Query Engine API to interact with the database layer at a lower level
strapi.db.query("api::news-list.news-list").findMany({})
The Query Engine allows operations on database entries,
I wrote this for my purpose probably you should change based on what you needed
{
where: {
locale: locale,
$not: {
id: id_nin
},
publishedAt: {
$notNull: true,
},
},
sort: [{ datetime: 'asc' }],
limit: 10,
populate: {
content: {
populate: {
thumbnail: true,
},
},
}
}
when you get data from your query, passed it to that function getRandomElementsFromArray(newsListArray, 2) to get some random item (how many random items do you want ? pass the second parameter)
At least if your array is null return null otherwise return data
create the controller
Controllers are JavaScript files that contain a set of methods, called actions, reached by the client according to the requested route so we going to call our services in this section
// path: ./src/api/[your-endpoint]/controllers/[your-endpoint].js
'use strict';
/**
* news-list controller
*/
const { createCoreController } = require('#strapi/strapi').factories;
module.exports = createCoreController('api::news-list.news-list', ({ strapi }) => ({
async random(ctx) { // name of this methods related to something we define in route ("handler": "[your-endpiont].random",)
const entity = await strapi.service('api::news-list.news-list').serviceGetRandom(ctx.query) // call our services, you can send all query you get from url endpoint (notice that you should write your endpoint api in strapi.service("your-endpoint"))
const sanitizedEntity = await this.sanitizeOutput(entity, ctx);
return this.transformResponse(sanitizedEntity);
// console.log(entity);
}
}));
I call this endpoint in my project nextjs & stapi cms
export const getRandomNewsItem = (id, locale) => {
return API
.get(`/news-list/random?locale=${locale}&id_nin=${id}`)
.then(res => res.data);
};
That's it, I'll hope you all get what to do
all resources you need
https://docs.strapi.io/developer-docs/latest/development/backend-customization/routes.html#creating-custom-routers
https://docs.strapi.io/developer-docs/latest/development/backend-customization/services.html#implementation
https://docs.strapi.io/developer-docs/latest/development/backend-customization/controllers.html#adding-a-new-controller
https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/query-engine-api.html
https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/query-engine/filtering.html#and
https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/entity-service/order-pagination.html#ordering
https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/entity-service/order-pagination.html#ordering
https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/query-engine/populating.html
I developed a simple API that is supposed to GET data from MongoDB Atlas. Unfortunately, if I directly hit the browser or use Postman, I am getting an error:
Cannot GET /api/rooms/getallrooms
server.js
const express = require('express');
const app = express();
const dbConfig = require('./db');
const roomsRoute = require('./routes/roomsRoute');
app.use('api/rooms', roomsRoute);
const port = process.env.PORT || 5001;
app.listen(port, () => {
console.log(`Server started on port ${port} :)`);
});
roomsRoute.js:
const express = require('express');
const router = express.Router();
const Room = require('../models/rooms');
router.get('/getallrooms', async (req, res) => {
try {
const rooms = await Room.find({});
return res.json({rooms});
} catch (error) {
return res.status(400).json({message: error});
}
});
module.exports = router;
rooms.js (Contains room schema):
const mongoose = require('mongoose');
const roomSchema = mongoose.Schema({
name : {
type: 'String',
required: true,
},
capacity : {
type: 'number',
required: true,
},
contact : {
type: 'number',
required: false,
},
type : {
type: 'String',
required: true,
},
imageURLs : [],
currentBookings : [],
description : {
type: 'String',
required: false,
},
rentPerDay : {
type: 'number',
required: true,
}
},{
timestamps: true,
});
const roomModel = mongoose.model('rooms', roomSchema);
module.exports = roomModel;
My Atlas looks like this:
I have ensured from Network Access that all IP connections are allowed (0.0.0.0/0).
This is my first API so I reckon I'm missing something basic. Can anybody help me figure this out?
Update 1:
By adding "/" in app.use, the error is gone but I'm getting empty response from the DB:
{
"rooms": []
}
Update 2:
After ensuring column names in model and DB are synchronised, still the response I'm getting is empty.
Here:
app.use('api/rooms', roomsRoute);
I think you need to prefix the path with a / like so:
app.use('/api/rooms', roomsRoute);
See the Express documentation for path examples.
The problem is with database URL. By default MongoDB gives the URL of "test" database. Updating the database name fixed the problem for me.
I am trying the following things:
1 Getting request body (Which is embedded with an Array).
2 Then After getting the request body I am trying to save all the objects in the array into my key of schema called "ExtraInfo".But When I run the API My "ExtraInfo" key has only object id without data.
I have Explained my whole question with my code and in my API Code, I have mentioned my logic with a comment where I am trying to push my array data to my "ExtraInfo" key.
Model:
const mongoose = require('mongoose');
const ExtraInfoModel = mongoose.Schema({
title:String,
body:String,
date: Date
})
const EmbeddedDataModel = mongoose.Schema({
class:Number,
ExtraInfo:[ExtraInfoModel],
})
module.exports = mongoose.model('EmbeddedDataCluster',EmbeddedDataModel);
RequestBody:
{
"class":"96",
"ExtraInfo":[
{
"title":"new1",
"body":"dummy1"
},
{
"title":"new2",
"body":"dummy2"
},
{
"title":"new3",
"body":"dummy3"
},
{
"title":"new4",
"body":"dummy4"
},
{
"title":"new5",
"body":"dummy5"
}
]
}
Now My Api
Router.post('/Embed', async (req, res) => {
const _ExtraInfo = await req.body.ExtraInfo;
console.log(_ExtraInfo);
try {
const _EmbeddedDataModel = await new EmbeddedDataModel({
class: req.body.class,
ExtraInfo:{$push:{$in:_ExtraInfo}}//Here is trying to loop through
//each object from array and trying to push in Key But when the Data
// saved the "ExtraInfo" key is empty and only have object id
});
_EmbeddedDataModel.save();
console.log(_EmbeddedDataModel);
res.json(_EmbeddedDataModel);
} catch (error) {
console.log(error);
res.json(error);
}
})
Result of DB:
{
"_id": "601a1f0e9fcda33570f9e26b",
"class": 96,
"ExtraInfo": [
{
"_id": "601a1f0e9fcda33570f9e26c"
}
]
}
Please Help me
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!
I am trying to make the following get request, which is intended to simply return documents from a collection. Once I get the data, it should flow through a reducer into the redux state object. But the get request fails.
var QuestionModel = require('./src/models/fv-questionModel')
mongoose.connect('mongodb://localhost/FVDB')
var app = express();
app.use(compression())
app.use(express.static(path.join(__dirname, 'public')));
app.set('port', process.env.PORT || 8080);
app.get('/api/recent', (request, response) => {
if (error) {
console.log(error)
}
// Get documents and perform callback on recentQuestions data
QuestionModel.find((error, recentQuestions) => {
if (error) {
response.send('unable to retrieve data')
} else {
response.json(recentQuestions)
}
})
})
this request was working until I changed the structure of the data in the collection. Here is my current mongoose schema:
const questionSchema = new mongoose.Schema({
title: String,
options: [{ oid: Number, choice: { name: String, count: Number } }],
qid: Number,
})
const QuestionModel = mongoose.model('Question', questionSchema, 'questionBank')
module.exports = QuestionModel
The previous schema:
const questionSchema = new mongoose.Schema({
title: String,
options: Array,
qid: Number,
})
Here is the Redux action that makes the GET request:
export function recentQuestions() {
let recentQs = axios.get('/api/recent')
return {
type: 'GET_RECENT',
payload: recentQs,
}
}
And the reducer to handle that data:
export default function(state = null, action) {
switch (action.type) {
case 'GET_RECENT':
return action.payload.data
}
return state
}
But when the GET request is made, it returns a '404: Not Found' error. When I navigate my browser to localhost:8080/api/recent I get the message 'cannot GET /api/recent'. The express server itself is working.
I cannot for the life of me figure out why this request is no longer working. I know there are other questions about failed GET requests but none seem to pertain to this issue. Any help would be greatly appreciated.