Why is req./body.param through a GET request undefined? - node.js

my issue is that req.body.param is undefined but body itself returns the wanted json from the requested source.
This means my iteration wont work too because i need to access req.body.data.length or the count of the id param available.
Thats also why i set num of iterations to 5 to test the output.
Project is created via the express-generator(body-parser is installed).
This is what i get returned
[
{
__v: 0,
id: "0",
appid: 730,
updated_at: "2016-06-05T16:52:39.742Z",
_id: "575458d71d1c41f414e3b29a",
created_at: "2016-06-05T16:52:39.731Z"
},
{
__v: 0,
id: "1",
appid: 730,
updated_at: "2016-06-05T16:52:39.749Z",
_id: "575458d71d1c41f414e3b29b",
created_at: "2016-06-05T16:52:39.737Z"
}, ...
]
This is how the requested api json body looks like:
{
data: [
{
id: 1,
product_name: "Product1",
app: appName,
quantity: 137360,
price: 0.05,
updated_at: "2016-06-04 23:02:03",
median_week: 0.04,
median_month: 0.05,
},
{
id:2,
...,
}
.....
{
id:142640,
...,
}
}
My Function
router.get('/', function(req, res) {
request.get('url/api/items/all/', function (error, response, body) {
console.log(options);
console.log('###########\n '+ body + '\n');
console.log('error '+error);
console.log('req:body '+req.body.data);
if (error && response.statusCode !== 200) {
// request could not be completed
return res.send(400, {message: 'Something went wrong'});
} else {
// get the count
//console.log('body.id.length: '+req.body.id.length);
//console.log('body.data.length: '+req.body.data.length);
//console.log('data.length: '+data.length);
var iterator = 5;//req.body.data.length; //|| req.body.num_items;
// iterate number of times
async.times(iterator, function(number, next){
console.log('iterating'+ number);
var newItem = Item({
id: number,
market_hash_name: req.body.market_hash_name,
appid: '730',
quantity: req.body.quantity,
price: req.body.price,
median_week: req.body.median_week,
median_month: req.body.median_month,
average_median_week: req.body.average_median_week,
trend_week: req.body.trend_week,
trend_month: req.body.trend_month,
total_sold_week: req.body.total_sold_week,
total_sold_month: req.body.total_sold_month,
updated_at: req.body.updated_at
})
// save andt
// call next (which is callback)
newItem.save(next);
}, function(timesErr, timesResult){
// if something failed, return error
// even if 1 item failed to save, it will return error
if(timesErr) {
return res.send(400, {message: 'Something went wrong'});
}
// send the list of saved items;
// or whatever you want
res.status(200).send(timesResult);
});
}
});
});
This Problem is referred to this issue

Try this code
var app = require('express')();
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.get.....

This question is old. For anyone having the same problem here is the Solution. You have to parse body content to json after that you´ll be able to access the param´s. like so const content = JSON.parse(body)

Related

Mongodb How to update documents already found

I'm building a movie rating system.
After entering the user ID, content ID, and rating registered in the rating document,
It was implemented by updating the rating in the content document.
How can I update the content document while I have already found it like the code below?
router.post('/', authenticate, async (req: IRequest<IRating>, res) => {
try {
const document = await Rating.create({
contentId: req.body.contentId,
contentType: req.body.contentType,
rating: req.body.rating,
review: req.body.review,
userId: req.user?._id,
});
const content = await Content.findOne({
type: req.body.contentType,
_id: document._id,
});
if (content) {
await content.updateOne(
{},
{
average: (content.average + document.rating) / content.count + 1,
count: content.count + 1,
},
);
}
res.json({ success: true, document, content });
} catch (err) {
res.status(404).json({ success: false, message: 'sever error' });
}
});
You can update with pipeline instead of use 2 queries, which for your current code can look like:
await Content.findOneAndUpdate(
{
type: req.body.contentType,
_id: document._id,
},
[{$set: {
average: {$divide: [{$add: ["$content.average", document.rating]},
{$add: ["$content.count", 1]}]},
count: {$add: ["$content.count", 1]}
}}])
But I don't think this is the right way to calculate an average. You should consider multiplying the existing $content.average by $content.count before adding the new document.rating

Maching ids doesn't return true when compared

I'm trying to make some comprobations on my API (Node.js + Mongodb)
I want to check if the proposerId is equal to the eventOrganizer. To do so
I'm sending this on the body:
{
"participantId": "6238a608170aff10d16ccd89",
"proposerId": "62385d8caee17d13a1762b39", // this guy id is also an organizer
"gender": "female",
"groupId": "623aea21fcfad83bcf8d5bc4"
}
in my PATCH controller to add a user I have this verification:
exports.addParticipantToEvent = async (req, res, next) => {
// Group Organizer constants
const eventId = req.params.eventId;
const groupId = req.body.groupId;
const proposerId = req.body.proposerId; // it can be an admin adding someone to the participants list
// Participant constants
const participantId = req.body.participantId;
const gender = req.body.gender;
// EVENT
// Does the event even exist?
const eventData = await Event.findById(eventId);
if (!eventData) {
return res.status(406).json({
code: 'EVENT_DOESNT_EXIST',
message: 'The event is not valid.',
});
}
console.log(eventData);
// What kind of users can participate in this event?
const allowedParticipants = eventData.allowedParticipants;
// whos the event organizer?
const eventOrganizer = eventData.organizer._id;
console.log('Organizer: ' + eventOrganizer);
console.log('Proposer: ' + proposerId);
console.log('Result: ' + proposerId === eventOrganizer);
try {
return res.status(200).json({
message: 'The participant can be added',
participantId: participantId,
gender: gender,
allowedParticipants: allowedParticipants,
});
} catch (err) {
return res.status(400).json({ message: err });
}
};
I want to verify is the proposerId is an admin or an organizer of the event, so I console.log the eventData entirely and later I console log all the constants I want to verify and the result, it gives me false all the time.
Maybe I need to specify better something?
{
location: { province: 'Barcelona' },
_id: new ObjectId("634ffee75990124926431e6f"),
title: 'Test open close 14',
sport: new ObjectId("622ce6ca672c3d4447676705"),
group: new ObjectId("623aea21fcfad83bcf8d5bc4"),
organizer: new ObjectId("62385d8caee17d13a1762b39"),
participants: [ new ObjectId("62385d8caee17d13a1762b39") ],
replacements: [],
invitations: [],
when: 2022-10-09T13:43:02.999Z,
open: true,
costPerParticipant: 4.4,
skill: 'novice',
allowedGender: 'female',
minParticipants: 2,
maxParticipants: 5,
visible: false,
externalLink: 'https://www.komoot.es/tour/731122050?ref=wta',
allowInvitations: true,
allowReplacements: false,
allowedParticipants: 'only-members',
createdAt: 2022-10-19T13:43:03.006Z,
updatedAt: 2022-10-19T13:43:03.006Z,
__v: 0
}
Organizer: 62385d8caee17d13a1762b39
Proposer: 62385d8caee17d13a1762b39
false
As you can see, both Organizer and proposer are same id, yet I get false.
After lurking some more, I have found that to validate mongos object ids with strings I need to use equals(). So now I have the solution.

Writing to MongoDB fails silently during Neo4j session.run() but works fine normally

The problem is that everything works fine in isolation, but as soon as I combine the Log.create(obj) into the Neo4j result stream, it stops working and what I assume is some Promise behaviour is eating all log information so I can't figure out why exactly it's not working or how to force it to display meaningful information.
I have been trying to diagnose this for the past 2 days, but I can't figure out why.
I have 2 files:
example.js and E1Logger/index.js
The logger file is simply the schema and models for a method that writes an object to MongoDB. It works fine if I comment out the bottom half of example.js.
I've tried probably like 20 different combinations of chaining promises, catching, done, exec, making it more asynchronous, making it more synchronous, and I can't seem to get any meaningful information.
I'm dying to know what is required to make it work.
example.js
//var config = require('./config');
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/major', error => { if (error) { console.error('ERROR: ' + error) }});
//mongoose.Promise = global.Promise;
var neo4j = require('neo4j-driver').v1;
var config = {};
config.neo4jHost = 'bolt://localhost:7687';
config.neo4jUser = 'neo4j';
config.neo4jPassword = 'garbagepassword';
var driver = neo4j.driver(config.neo4jHost, neo4j.auth.basic(config.neo4jUser, config.neo4jPassword));
var E1Logger = require('./E1Logger');
let newInfoLog = {
logType: 'INFO',
eventType: 'Purge Stale Invite',
result: 'Success',
invitedByUser: {
neo4jNodeID: 123,
name: 123 + ' ' + 321,
email: 123
},
purgedUser: {
neo4jNodeID: 123,
email: 123
},
createdAt: 123,
expirationAt: 123
};
let newErrorLog = {
logType: 'ERROR',
eventType: 'Purge Stale Invite',
result: 'Fail',
reason: 123,
attemptedQuery: 123,
};
E1Logger.info(newInfoLog);
E1Logger.error(newErrorLog);
// Calculate cutoff time for expired invites and form the Cypher Query
var currentTime = new Date().getTime();
var sliceTime = currentTime - 604800000; // 604800000 milliseconds in one week
var cypherQuery = 'MATCH (e:Person)-[r:INVITED_TO_APP]->(x) WHERE r.expirationAt<=\'' + sliceTime + '\' AND r.status=\'pending\' RETURN id(e) as invitedByUserId, e.given_name as invitedByUserFirstName, e.family_name as invitedByUserLastName, e.email as invitedByUserEmail, r.createdAt as createdAt, r.expirationAt as expirationAt, id(x) as purgedUserId, x.email as purgedUserEmail';
// Execute Purge Event
var session = driver.session();
session
.run(cypherQuery)
.then(function(result){
result.records.forEach(function(record) {
// Generate log for each expired invite
let newInfoLog = {
logType: 'INFO',
eventType: 'Purge Stale Invite',
result: 'Success',
invitedByUser: {
neo4jNodeID: record.get('invitedByUserId').low,
name: record.get('invitedByUserFirstName') + ' ' + record.get('invitedByUserLastName'),
email: record.get('invitedByUserEmail')
},
purgedUser: {
neo4jNodeID: record.get('purgedUserId').low,
email: record.get('purgedUserEmail')
},
createdAt: record.get('createdAt'),
expirationAt: record.get('expirationAt')
};
// Log result
console.log('PURGED: ' + JSON.stringify(newInfoLog));
E1Logger.info(newInfoLog);
});
session.close();
driver.close();
})
.catch(function(error) {
// Generate log for failed purge
let newErrorLog = {
logType: 'ERROR',
eventType: 'Purge Stale Invite',
result: 'Fail',
reason: error,
attemptedQuery: cypherQuery,
};
// Log result
console.log('ERROR: ' + JSON.stringify(newErrorLog));
E1Logger.error(newErrorLog);
//session.close();
//driver.close();
});
mongoose.disconnect();
E1Logger/index.js
const mongoose = require('mongoose');
// Define Info Log Schema
const InfoLogModel = mongoose.model('Infolog', new mongoose.Schema({
logType: String,
loggedAt: { type: Number, default: new Date().getTime() },
eventType: String,
result: String,
invitedByUser: {
neo4jNodeID: Number,
name: String,
email: String
},
purgedUser: {
neo4jNodeID: Number,
email: String
},
createdAt: Number,
expirationAt: Number
}));
// Define Error Log Schema
const ErrorLogModel = mongoose.model('Errorlog', new mongoose.Schema({
logType: String,
loggedAt: { type: Number, default: new Date().getTime() },
eventType: String,
result: String,
reason: String,
attemptedQuery: String,
}));
module.exports = {
// Define Info Log Model
info: function(eventData) {
InfoLogModel.create(eventData, (error, addedEvent) => {
if (error) throw error;
console.log('INFO: ' + addedEvent);
});
},
// Define Error Log Model
error: function(eventData) {
ErrorLogModel.create(eventData, (error, addedEvent) => {
if (error) throw error;
console.log('ERROR: ' + addedEvent);
});
}
};
I suspect the problem is at ErrorLogModel.create(eventData). I've never been able to get it to write to MongoDB from inside session.run(). A had a couple combinations that were showing something about a promise rejection, but that's as close as I got. I recall something like ErrorLogModel.create(eventData).catch( err => console.log('ok') ); made it do that.
Am I missing something about promises here? Why does functional code working code through Neo4j session.run().then() cause it to stop working? Is it maybe a bug I should report to Mongoose or Neo4j?

Mongoose Subdocument will not update

I am having trouble figuring out if I designed the schema correctly because I am receiving a 500 error when attempting to PATCH changes of the roles property from a profile. (Note: The 500 error just responds with an empty {}, so it isn't really informative)
Below is the profile schema:
var ProfileSchema = new Schema({
name: {
type: String,
required: true
},
roles: [{
application: {
type: Schema.Types.ObjectId,
required: true,
ref: 'Application'
},
role: {
type: String,
required: true,
enum: [ 'admin', 'author', 'publisher' ]
}
}]
});
Each profile has a role for an application, and when I send the request to the controller action 'update', it fails:
profile update controller:
// Updates an existing Profile in the DB
export function update(req, res) {
try {
if (req.body._id) {
delete req.body._id;
}
console.log('ENDPOINT HIT...');
console.log(`REQUEST PARAM ID: ${req.params.id}`);
console.log('REQUEST BODY:');
console.log(req.body);
console.log('ENTIRE REQUEST: ');
return Profile.findByIdAsync(req.params.id)
.then(handleEntityNotFound(res))
.then(saveUpdates(req.body))
.then(respondWithResult(res))
.catch(handleError(res));
} catch(ex) {
console.error('FAILED TO UPDATE PROFILE');
return handleError(res);
}
}
I made sure that the id and body was being sent properly, and I am hitting the end point.
This is an example of the request body JSON:
{
_id: 57e58ad2781fd340563e29ff,
__updated: Thu Oct 27 2016 15:41:12 GMT-0400 (EDT),
__created: Fri Sep 23 2016 16:04:34 GMT-0400 (EDT),
name: 'test',
__v: 11,
roles:[
{ application: 57b70937c4b9fe460a235375,
role: 'admin',
_id: 58125858a36bd76d8111ba16 },
{ application: 581b299f0145b48adf8f57bd,
role: 'publisher',
_id: 581b481898eefb19ed8a73ee }
]
}
When I try to find the Profile by Id, the promise chain goes straight to the catch(handleError(res)); part of the code and shows an empty object in my console.
My handle error function:
function handleError(res, statusCode) {
console.error('HANDLE PROFILE ERROR: ', statusCode);
statusCode = statusCode || 500;
return function(err) {
console.error('PROFILE ERROR:');
console.error(JSON.stringify(err, null, 2));
res.status(statusCode).send(err);
};
}
UPDATE
I am realizing the code is breaking when it hits my saveUpdates function (Note: I am using lodash):
function saveUpdates(updates) {
/// the code is fine here ///
return function(entity) {
/// once it enters in here, is where it begins to break ///
var updated = _.merge(entity, updates);
if(updated.roles.length != updates.roles.length) {
updated.roles = updates.roles;
}
for(var i in updates.roles) {
updated.roles.set(i, updates.roles[i]);
}
return updated.saveAsync()
.then(updated => {
return updated;
});
};
}
Lesson learned: Read Documentation properly.
Since I am using bluebird promises for this application, I forgot to use .spread() within my saveUpdates() callback function.
Solution:
function saveUpdates(updates) {
return function(entity) {
var updated = _.merge(entity, updates);
if(updated.roles.length != updates.roles.length) {
updated.roles = updates.roles;
}
for(var i in updates.roles) {
updated.roles.set(i, updates.roles[i]);
}
return updated.saveAsync()
// use `.spread()` and not `.then()` //
.spread(updated => {
return updated;
});
};
}
I want to thank the following SOA that led to this conclusion: https://stackoverflow.com/a/25799076/5994486
Also, here is the link to the bluebird documentation in case anyone was curious on .spread(): http://bluebirdjs.com/docs/api/spread.html

ElasticSearch TypeError: Request path contains unescaped characters

I am writing server code that listens for search requests on the firebase database and return the search result. This is the code that indexes the data from Firebase Database to Elastic Search. Is this the correct way to index data?
var firebase = require('firebase');
var ElasticClient = require('elasticsearchclient');
// listen for changes to Firebase data
var client = new ElasticClient({host:'localhost',port:9200});
firebase.initializeApp({
serviceAccount: {
...
},
databaseURL: "https://searchserver.firebaseio.com/"
})
var db = firebase.database();
var ref = db.ref("realtime");
ref.on('child_added', upsert);
ref.on('child_changed', upsert);
ref.on('child_removed', remove);
function upsert(snap) {
client.index({
index: 'firebase',
type: 'users',
id: snap.key,
body: snap.val()
}, function (err, response) {
if (err) {
console.log("error indexing " + error)
}
});
}
function remove(snap) {
client.delete({
index: 'firebase',
type: 'users',
id: snap.key
}, function (error, response) {
if (error) {
console.log("Error deleting user : " + error);
}
});
}
This is the error message.
TypeError: Request path contains unescaped characters.
at new ClientRequest (_http_client.js:50:11)
at Object.exports.request (http.js:31:10)
at ElasticSearchCall.exec (C:\Users\jojo\Documents\readouts-search\readouts-server\node_modules\elasticsearchclient\lib\elasticsearchclient\calls\elasticSearchCall.js:45:26)
at ElasticSearchClient.createCall (C:\Users\jojo\Documents\readouts-search\readouts-server\node_modules\elasticsearchclient\lib\elasticsearchclient\elasticSearchClient.js:28:14)
at ElasticSearchClient.index (C:\Users\jojo\Documents\readouts-search\readouts-server\node_modules\elasticsearchclient\lib\elasticsearchclient\calls\core.js:37:17)
at upsert (C:\Users\jojo\Documents\readouts-search\readouts-server\readouts-server.js:28:12)
at C:\Users\jojo\Documents\readouts-search\readouts-server\node_modules\firebase\database-node.js:146:375
at Qb (C:\Users\jojo\Documents\readouts-search\readouts-server\node_modules\firebase\database-node.js:43:165)
at nc (C:\Users\jojo\Documents\readouts-search\readouts-server\node_modules\firebase\database-node.js:31:216)
at oc (C:\Users\jojo\Documents\readouts-search\readouts-server\node_modules\firebase\database-node.js:30:701)
Value of snap.val()
{ '5Nyu7Px7vNYGizJqlyGHhAfnvwu2':
{ allOwnerVideos: 'none',
allRatedVideos: 'none',
email: 'iron#man.com',
favorite_category:
{ fifth: 'Business',
first: 'Sports',
fourth: 'Biography',
second: 'Sci-Fi',
seventh: 'Action and Adventure',
sixth: 'Art',
third: 'Satire' },
name: 'iron',
personalmessage: 'man',
profileimage: 'https://firebasestorage.googleapis.com/v0/b/readoutsa75e0.appspot.com/o/ProfilePictures%2F_5Nyu7Px7vNYGizJqlyGHhAfnvwu2.jpg?alt=media&token=743dbd6a-985c-4481-9d63-4ed30e8703a9' },
'6bt3EqdWyfQ3ksEdy9BTyYvQK4F3'

Resources