I'm developing a node js rest server and having an issue with my Schema queries. When I hit my end points I get the error TypeError: user.find is not a function
The following is my user.js file
var {mongoose} = require('../../dbcore/mongoose');
var Schema = mongoose.Schema;
module.exports = mongoose.model('User',new Schema( {
basicId: Schema.ObjectId,
activePurchaseIDs: {
type: [Schema.ObjectId],
default: []
},
activeOrderIDs: {
type: [Schema.ObjectId],
default: []
},
paymentOptionIDs: {
type: [Schema.ObjectId],
default: []
},
addressIDs: {
type: [Schema.ObjectId],
default: []
},
interestIDs: {
type: [Schema.ObjectId],
default: []
}
}));
and this is where it's imported/required.
var URLS = require('./urls');
var User = require('../schemas/user/user');
function init(app,mongoose) {
app.get(URLS.USERS_URL,(req,res)=>{
var user = new User({});
user.find().then((users)=>{
res.send({users});
},(err)=>{
res.status(400).send(err);
});
});
}
module.exports = init;
I was following a tutorial while writing this code and I was expecting it to work as I followed the tutorial step by step.
When you call var user = new User({}) you are creating a new MongoDB document based on the User model and assigning it to var user.
A single user document does not have a find() function, but your User model does.
var user = new User({});
User.find().then(...);
app.get(URLS.USERS_URL, async (req,res)=>{
const userList = await User.find();
if(!userList) {
res.status(500).json({success: false});
}
res.send(userList);
});
Your call to the database needs to look like this:
User.find().then((users)=>{
res.send({users});
}).catch((err)=>{
res.status(400).send(err);
});
You should call it directly on the module, because mongoose will handle creation implicitly and creating a new object isn't neccesary.
I'm not sure if your schema is correctly defined, but I'm not going to say your tutorial is wrong on that. You should go into mongo shell and check if the schema was created to verify it was designed correctly.
In my case, I wrote wrong this so check your file exports module.exports = XYZ format.
PS:- I wrote like this exports.module = XYZ
Related
I'm new to both Strapi and Mongoose, so I apologise if this is a stupid question.
Following the docs (https://strapi.io/documentation/developer-docs/latest/development/backend-customization.html) I'm trying to create a custom query in Strapi in which I want to return the whole collection called people sorted by name desc. But when I hit the endpoint I get a 500 error and checking the terminal the error message is CastError: Cast to ObjectId failed for value "alldesc" at path "_id" for model "people".
Here's my code:
services/people.js
module.exports = {
findByNameDesc() {
const result = strapi
.query("people")
.model.find()
.sort({ name: "descending" });
return result.map((entry) => entry.toObject());
},
};
controllers/people.js
module.exports = {
async alldesc(ctx) {
const entities = await strapi.services.people.findByNameDesc(ctx);
return entities.map((entity) =>
sanitizeEntity(entity, { model: strapi.models.people })
);
},
};
config/routes.json
{
"routes": [
...
{
"method": "GET",
"path": "/people/alldesc",
"handler": "people.alldesc",
"config": {
"policies": []
}
}
]
}
What am I doing wrong?
UPDATE: even when removing .sort({ name: "descending" }); from the query, the error is still there, so I'm thinking that maybe there's something wrong in the way I use the service in the controller?
The problem was in routes.json. Basically seems like Strapi doesn't like the slash / so instead of /people/alldesc I tried /people-alldesc and it worked.
Also in the service there's no need for return result.map((entry) => entry.toObject());, that causes anther error, simply doing return result works.
I want to user commander.js and inquirer.js to ask questions and collect the answer to create a User instance:
// index.js
const mongoose = require('mongoose');
const User = require('./model/user')
const {addUser,listAllUsers,findUserByEmail,updateUser,deleteUser} = require('./model_methods/user_methods')
const { program } = require('commander');
var inquirer = require('inquirer');
// connect to DB
const db = mongoose.connect('mongodb://localhost:27017/myImportantDates', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const questions = [
{
type: 'input',
name: 'email',
message: 'user email'
},
{
type: 'input',
name: 'name',
message: 'user name'
},
{
type: 'input',
name: 'password',
message: 'user password'
},
];
program
.version('0.0.1')
.description('The important dates app');
program
.command('add')
.alias('a')
.description('Add a user')
.action(
inquirer
.prompt(questions)
.then( answers => {
addUser(answers)
})
.catch(err =>{
console.log(error)
})
)
program.parse(process.argv);
When I run it with node index.js add, the questions array ask one question and quit:
#DESKTOP-5920U38:/mnt/c/Users/myApp$ node index.js add
? user email
#DESKTOP-5920U38:/mnt/c/Users/myApp$
When I delete program.parse(process.argv), however, everything works fine, it can return me the new User instance.
I check the documents: https://github.com/tj/commander.js/
Still have no idea what happened. Does anybody know more about this??
What I found just now is that if I put program.parse(process.argv) in the beginning like this in the first set up of the program instance:
program
.version('0.0.1')
.description('The important dates app')
.parse(process.argv);
It works too. But I still don't know why the order matters.
In Node.js, process.argv is an array containing the command line arguments passed when the Node.js process was launched. So, program.parse(process.argv) parses the the command line options for arguments, which is bypassing your inquierer.js prompt. You can leave it out.
program.parse(process.argv) is called after setting up your program. It takes the command line arguments (process.argv) and parses them using your declared program, displaying errors or calling action handlers etc.
Based on your example code, an issue is the action handler takes a function parameter. e.g.
.action(() => {
// code goes here
});
I have implemented a page where students can enter in a their Coursework Name with its intended milestones. However, I want to add validation that will only allow users to enter using the following method, two strings with a ':' between them. For example - 'Coursework : Milestone'. Any length of string accepted, as long as it ensures there are two strings with a ':' to separate them in the middle as seen in the example. I am very new to Node.js, Express, jQuery and Handlebars and I have searched for ways to do this but none seemed useful. Below is the only code needed.
in the controller file, a section for creating a new input data
const Task = require('../models/task');
create: function(req, res) {
Task
.create(req.body)
.then(result => {
// result.sort(sortTask)
res.json(result)
})
.catch(err => res.json(err));
}
the model file, task.js, for reference
//dependency
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
//data inputted into the database, coursework/milestones section, validation included
const taskSchema = new Schema({
task: {
type: String,
},
completed: {
type: Boolean,
default: false
},
addedAt: {
type: Date,
default: Date.now()
},
});
const Task = module.exports = mongoose.model('Task', taskSchema);
jQuery code to allow these actions to work, in the public folder, eventListeners.js file
$(document).ready(function() {
//index page events
//click even for creating a milestone/coursework
$('#create').on('click', function(e) {
createTask(e);
});
//keypress event that allows milestone?coursework to be created on 'Enter'
$('#task').keypress(function(e) {
if (e.key === 'Enter') {
createTask(e);
}
});
the index.hbs file input section
<input type="text" class="form-control" placeholder="Coursework : Milestone" id="task" autofocus>
RegExp.prototype.test() is what you're looking for. In your use case:
/:/.test(<user input>)
I have a very basic feathers service which stores data in mongoose using the feathers-mongoose package. The issue is with the get functionality. My model is as follows:
module.exports = function (app) {
const mongooseClient = app.get('mongooseClient');
const { Schema } = mongooseClient;
const messages = new Schema({
message: { type: String, required: true }
}, {
timestamps: true
});
return mongooseClient.model('messages', messages);
};
When the a user runs a GET command :
curl http://localhost:3030/messages/test
I have the following requirements
This essentially tries to convert test to ObjectID. What i would
like it to do is to run a query against the message attribute
{message : "test"} , i am not sure how i can achieve this. There is
not enough documentation for to understand to write or change this
in the hooks. Can some one please help
I want to return a custom error code (http) when a row is not found or does not match some of my criterias. How can i achive this?
Thanks
In a Feathers before hook you can set context.result in which case the original database call will be skipped. So the flow is
In a before get hook, try to find the message by name
If it exists set context.result to what was found
Otherwise do nothing which will return the original get by id
This is how it looks:
async context => {
const messages = context.service.find({
...context.params,
query: {
$limit: 1,
name: context.id
}
});
if (messages.total > 0) {
context.result = messages.data[0];
}
return context;
}
How to create custom errors and set the error code is documented in the Errors API.
Basically, I am trying to get a wss feed going from Poloniex, and update a collection with it so that I can have 'latest' prices in a collection (I will update and overwrite existing entries) and show it on a web page. For now, I got the wss working and am just trying to insert some of the data in the collection to see if it works, but it doesn't and I can't figure out why!
Note: The collection works, I've manually inserted a record with the shell.
Here is the code I have now:
import { Meteor } from 'meteor/meteor';
import * as autobahn from "autobahn";
import { Mongo } from 'meteor/mongo'
import { SimpleSchema } from 'meteor/aldeed:simple-schema'
//quick DB
Maindb = new Mongo.Collection('maindb');
Maindb.schema = new SimpleSchema({
place: {type: String},
pair: {type: String},
last: {type: Number, defaultValue: 0}
});
Meteor.startup(() => {
var wsuri = "wss://api.poloniex.com";
var Connection = new autobahn.Connection({
url: wsuri,
realm: "realm1"
});
Connection.onopen = function(session)
{
function tickerEvent (args,kwargs) {
console.log(args[0]);
Maindb.insert({place: 'Poloniex', pair: args[0]});
}
session.subscribe('ticker', tickerEvent);
Connection.onclose = function () {
console.log("Websocket connection closed");
}
}
Connection.open();
});
The console logs the feed but then the insert does not work.
I looked online and it said that to get an insert to work when in a 'non Meteor' function, you need to use Meteor.bindEnvironment which I did:
I changed
function tickerEvent (args,kwargs) {
console.log(args[0]);
Maindb.insert({place: 'Poloniex', pair: args[0]});
}
which became
var tickerEvent = Meteor.bindEnvironment(function(args,kwargs) {
console.log(args[0]);
Maindb.insert({place: 'Poloniex', pair: args[0]});
}); tickerEvent();
Which doesn't do anything - not even print the feed on my console. Using this same structure but simply removing Meteor.bindEnvironmentprints again to the console but doesn't update.
Am I doing something wrong?