I am starting to implement mongoose in a nodejs project. I have created a test record in a collection to test the CRUD operations from the back, I am trying to test the find() property of mongo but I am not sure how to do it.
This is my connection to mongoose:
const mongoose = require('mongoose');
const mongoURI: string = "mongodb://localhost:27017"
const mongoDB: string = "testdb"
export const setMongo = async() => {
try {
let mongodbURI: string = `${mongoURI}/${mongoDB}`
await mongoose.connect(mongodbURI);
console.log('conected DB')
} catch (error) {
console.log('error DB')
}
};
This is my Schema:
const mongoose = require('mongoose');
const companiesSchema = new mongoose.Schema ({
name: {
type: String,
required: true
},
phoneNumber: {
type: Number,
required: true,
unique: true
}
}, {
versionKey: false,
collection: 'companies'
});
module.exports = mongoose.model('Companies', companiesSchema);
This is my resposity.ts:
const companySchema = require("../../schemas/companies")
const db = companySchema.Companies
export class Repository {
public async getAll(): Promise<any> {
try {
console.log('getAll()')
const comp = await db.find({});
console.log(comp)
} catch (error) {
console.log(error)
}
}
}
This is the error it shows:
TypeError: Cannot read property 'find' of undefined
How should I create the connections or queries to mongo?
UPDATE
How can I get the total of the data with the find() method? Is it possible?
you just import your model in your controller and then you can use your query like:
const Companies = require("../../schemas/companies")
export class Repository {
public async getAll(): Promise<any> {
try {
console.log('getAll()')
const comp = await Companies.find({});
console.log(comp)
} catch (error) {
console.log(error)
}
}
}
and for get count of your result you can use .count() after your query to count your result :
const comp = await Companies.find({}).count();
Related
I'm trying to connect MongoDB Atlas and mongoose but server always returns an empty array '[ ]'. When I load a mock data everything works (Mocked data and MongoDB Atlas have the same values)
I have connect to MongoDB Atlas, but can't get some data.
Controller:
const express = require('express')
const { ApolloServer } = require('apollo-server-express')
const { createServer } = require('http')
const mongoose = require('mongoose')
const typeDefs = require('./schema')
const resolvers = require('./resolvers')
const app = express()
const server = new ApolloServer({
typeDefs,
resolvers,
playground: {
endpoint: 'http://localhost:3000/graphql',
settings: {
'editor.theme': 'light'
}
}
})
server.applyMiddleware({ app })
const httpServer = createServer(app)
server.installSubscriptionHandlers(httpServer)
mongoose
.connect(`mongodb+srv://<username>:<password>#cluster0.brdqp.mongodb.net/${process.env.mongoDatabase}?retryWrites=true&w=majority`, { useNewUrlParser: true, useUnifiedTopology: true })
.then((res) => {
httpServer.listen(3000, () => {
console.log('connected!')
})
})
.catch((err) => {
console.error('Error while connecting to MongoDB', err);
})
Schema:
const { gql } = require('apollo-server-express')
const typeDefs = gql`
type Todo {
_id: String,
title: String,
description: String
status: String
date: String
}
type Query {
todos: [Todo]
}
`
module.exports = typeDefs
Resolvers:
const { Todo, Restaurant, Customer, Order } = require('./models')
const pubsub = require('./pubsub')
const resolvers = {
Query: {
todos(parent, args, context, info) {
return Todo.find()
.then(todo => {
return todo.map(r => ({ ...r._doc }))
})
.catch(err => {
console.error(err)
})
},
},
}
module.exports = resolvers
MongoDB Atlas collection: (Database name : node, collection name in DB : todo)
_id : 5c9bdb721c9d440000345d62
title : "question"
desctiption : "test test"
status: done
date: 1
But the server always returns [ ]
How???? Why&?
This error is really frustrating especially as it is intermittent (it comes and goes). I'm using mongoose with express and typescript and I'm connecting to a database on MongoDB atlas. This is resulting into a bad user experience and it isn't really cool. The error message displayed says Operation wallets.findOne() buffering timed out after 10000ms. There are times the app runs fine and executes all operations as purposed but this error suddenly creeps out at some point. Below is my code and if you read through it, you'd see I'm using async await.
import mongoose from "mongoose";
import { Wallet } from "../../core/interfaces";
import { Tokenizers } from "../../core/utils";
export class WalletModel {
model: mongoose.Model<any>;
constructor() {
this.define();
}
private define() {
this.model = mongoose.model(
"Wallet",
new mongoose.Schema({
encryptedPrivateKey: String,
encryptedWallet: {
type: String,
required: true
}
})
);
}
async create(wallet: Wallet, privateKey: string): Promise<Wallet> {
const encryptedWallet = Tokenizers.encryptWallet(wallet);
const walletModel: any = await this.model.create({
encryptedPrivateKey: Tokenizers.encryptPrivateKey(
privateKey,
wallet.publicKey
),
encryptedWallet
});
const decryptedWallet: Wallet = Tokenizers.decryptWallet(
walletModel.encryptedWallet,
wallet.privateKey
);
return Promise.resolve(decryptedWallet);
}
async getWallet(privateKey: string, publicKey: string): Promise<Wallet> {
const encPrivateKey: string = Tokenizers.encryptPrivateKey(
privateKey,
publicKey
);
// Below find utilizes the indexing created on encryptedPrivateKey field
// and is way faster than linear search on whole collection
const encWallet: mongoose.Document & {
encryptedPrivateKey: string;
encryptedWallet: string;
} = (await this.model
.findOne({
encryptedPrivateKey: encPrivateKey
})
.lean()) as mongoose.Document & {
encryptedPrivateKey: string;
encryptedWallet: string;
};
const encryptedWallet: string = encWallet.encryptedWallet;
const decryptedWallet: Wallet = Tokenizers.decryptWallet(
encryptedWallet,
privateKey
);
return Promise.resolve(decryptedWallet);
}
async findByPrivateKey(privateKey: string): Promise<Wallet> {
let wallet: Wallet = null;
const allWallets = (await this.model.find().lean()) as any;
for (const doc of allWallets) {
const pk = Tokenizers.decryptPrivateKey(doc.encryptedPrivateKey);
if (pk === privateKey)
wallet = Tokenizers.decryptWallet(doc.encryptedWallet, privateKey);
}
return Promise.resolve(wallet);
}
async updateWallet(privateKey: string, newWallet: Wallet): Promise<Wallet> {
// const allWallets = await this.model.find();
let w: Wallet = null;
const updatedWallet = (await this.model
.findOneAndUpdate(
{
encryptedPrivateKey: Tokenizers.encryptPrivateKey(
privateKey,
newWallet.publicKey
)
},
{
encryptedWallet: Tokenizers.encryptWallet(newWallet)
},
{
new: true
}
)
.lean()) as mongoose.Document & {
encryptedWallet: string;
encryptedPrivateKey: string;
};
w = Tokenizers.decryptWallet(updatedWallet.encryptedWallet, privateKey);
return Promise.resolve(w);
}
}
Here's the content of the index.ts file where I'm starting all servers and making connections:
import express from "express";
import mongoose from "mongoose";
import config from "./config";
import { Environment } from "./env";
let app: express.Application = express();
const port = process.env.PORT || 7890;
app = config(app);
app.listen(port, async () => {
console.log(`Server listening on port ${port} in ${process.env.NODE_ENV}`);
const mongo = await mongoose.connect(
Environment.MONGO_URI[process.env.NODE_ENV],
{
useNewUrlParser: true,
useFindAndModify: false,
useCreateIndex: true
}
);
if (mongo) console.log("Connected to mongodb");
});
// Export app for tests
export default app;
try adding the index: true in your mongoose model. This can also happen if the database record is large, so making indexes can help find the document fast.
I am new to GraphQL and mongoose and trying to create a function in a resolver which creates a shawarma order, the inputs required are the shawarma ID, the quantity and an address, when I run the code typed below, I get an Error which states
TypeError: Cannot read property 'shawarmaOrdered' of undefined
the resolver code:
import mongoose from 'mongoose';
import AuthenticationError from 'apollo-server';
import {shawarma} from '../models/shawarmaModel';
export default {
Query:{
},
Mutation: {
createOrder: async(parent, {OrderInput}, {models: {orderModel, shawarmaModel}}, info) => {
console.log('reached1')
try{
const {shawarmaOrdered, quantity, address} = OrderInput;
const order = await orderModel.updateOne({shawarmaOrdered, quantity, address})
return order
} catch(err){
console.log('errorr')
console.log(err)
}
}
},
Order: {
shawarmaOrdered: async(parent, {shawarmaOrdered}, {models:shawarmaModel}, info) =>{
return shawarmaOrdered = shawarmaModel.find((shawarma)=>{
return shawarma.id == parent.id
})
}
}
the schema code:
import {gql} from 'apollo-server'
export default gql`
type Order{
id: ID!
shawarmaOrdered: Shawarma!
quantity: Int
orderedTo: String
}
input OrderInput{
shawarmaOrdered: ID!
quantity: Int
orderedTo: String
}
extend type Query {
order(id: ID!): Order!
}
extend type Mutation {
createOrder(shawarmaOrdered: String!, quantity: Int!, orderedTo: String!): Order!
}
`
the order model code:
import mongoose, { Mongoose } from 'mongoose'
import shawarma from './shawarmaModel'
const orderSchema = new mongoose.Schema({
shawarmaOrdered: {
type: mongoose.Schema.Types.ObjectId,
ref: shawarma
},
quantity: {
type: Number
},
completed: {
type: Boolean,
default: false
}
})
const order = mongoose.model('order', orderSchema)
export default order;
kindly let me know if I'm doing something wrong
So here's how I fixed the problem.
in the index.js file
import cors from 'cors';
import express from 'express';
import jwt from 'jsonwebtoken';
import mongoose from 'mongoose';
import { ApolloServer, AuthenticationError } from 'apollo-server-express';
import schemas from './schemas';
import resolvers from './resolvers';
import userModel from './models/userModel';
import orderModel from './models/orderModel';
import shawarmaModel from './models/shawarmaModel';
const app = express();
app.use(cors());
const getUser = async (req) => {
const token = req.headers['token'];
// console.log(token)
if (token) {
try {
return await jwt.verify(token, 'riddlemethis');
} catch (e) {
console.log(e)
throw new AuthenticationError('Your session expired. Sign in again.');
}
}
};
const server = new ApolloServer({
typeDefs: schemas,
resolvers,
context: async ({ req }) => {
if (req) {
const me = await getUser(req);
return {
me,
models: {
userModel,
orderModel, //this was where the orderModel was misspelled as OrderModel
shawarmaModel
},
};
}
},
});
server.applyMiddleware({ app, path: '/graphql' });
app.listen(5000, async () => {
await mongoose.connect('mongodbconnectionString')
});
in the code above, I have commented the section in which the error was from. Carelessly, when debugging I overlooked checking this file. my mistake. I apologise for not including this code in the original question
i am trying to fetch data from a MongoDB database using mongoose and express in Node js , i created the Model and successfully connected to database but the problem is i am getting an empty response while there already documents in the database collection .
Model class :
const mongoose = require("mongoose");
const RendezvousSchema = mongoose.Schema({
idpatient: {
type: String,
required: true
},
idmedecin: {
type: String,
required: true
},
});
module.exports = mongoose.model("Rendezvous", RendezvousSchema);
index.js :
const express = require("express");
const router = express.Router();
const Rendezvous = require("../model/RendezVous");
/* Get Rendez Vous By id */
/**
* #method - GET
* #description - Get Rendez vous Medecin
* #param - /user/GetRdvMedecin
*/
router.get("/GetRdvMedecin", async (req, res) => {
try {
const rdv = await Rendezvous.find();
res.json(rdv);
console.log('Fetched');
} catch (e) {
res.send({ message: "Error in Fetching rendez vous" });
}
});
/* Get Rendez Vous By id*/
module.exports = router;
this is the console.log :
Server Started at PORT 4000
Connected to DB !!
Fetched
Postman GET request on : 'http://localhost:4000/user/GetRdvMedecin'
Postman Response : ' [] '
document sample :
{
"_id":{
"$oid":"5e7396787b32a12e38a7aa7d"
},
"idpatient":"5e6ce11bc31de6132ca454a1",
"idmedecin":"5e5aa519190d8c2818a66a0a"
}
Hint : when i used another model ('user') it works fine and returns a response .
Your request .find() could return more than one object, I always return something like this:
router.get("/GetRdvMedecin", async (req, res) => {
let results;
try {
results = await Rendezvous.find();
} catch (e) {
res.send({ message: "Error in Fetching rendez vous" });
}
res.json({rendezvous: results.map(result => result.toObject({getters: true}) )});
});
Solved by adding the name of collection in the model
const mongoose = require("mongoose");
const RendezvousSchema = mongoose.Schema({
idpatient: {
type: String
},
idmedecin: {
type: String
}
},{
collection: 'Rendezvous'
});
// export model user with UserSchema
module.exports = mongoose.model("Rendezvous", RendezvousSchema);
I am trying to create a collection in mongodb where a field named lists will contain an array of link and linkName. I am successfully able to create a two seperate field link and linkName, however not able to store the value inside lists.
Model code for mongodb :-
const socialSchema = new Schema({
lists: [{
link:{ formType: String},
linkName: { formType: String}
}]
})
API code :-(this code is for creating only, will later on try to use findOneAndUpdate to update the existing field
router.route('/', [auth]).post(async (req, res) => {
const {linkName, link } = req.body
try {
console.log(req.body)//Ex. { linkName: 'facebook', link: 'www.facebook.com'}
const social = new Social({
//Stuck here!!!
})
await social.save()
res.json(social)
} catch (err) {
console.error(err.message);
res.status(500).send('Server Errors')
}
}
)
Part of frontend Code(React)
const [formData, setFormData] = useState({
linkName: '',
link: ''
});
const {linkName, link} = formData
const onChange = e =>
setFormData({ ...formData, [e.target.name]: e.target.value });
const handleSubmit = async e => {
e.preventDefault()
const socialList = {
linkName,
link
}
try {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const body = JSON.stringify(socialList)
const res = await Axios.post('/api/social', body, config)
console.log(res)
} catch (err) {
console.error(err);
}
}
In your schema change from {formType: String} to {type: String}.
const data = {link: req.body.link, linkName: req.body.linkName};
Social.create({
links: [data]
});
This should work.
MY FULL WORKING CODE THAT I TESTED
const schema = new mongoose.Schema({
links: [
{
link: { type: String },
linkName: { type: String }
}
]
});
const Model = mongoose.model("test", schema);
const doc = { link: "link", linkName: "linkname" };
Model.create({
links: [doc]
});