Node.JS cradle and couchDB assistance - node.js

I am a noob with Node.JS.
I am using CouchDB and Cradle.
In couchDB I have a database named 'test' and inside it I have a document named 'exercise'.
The document has 2 fields: "FullName" and "Age".
The code in order to save the data is as follows:
var cradle = require('cradle');
var connection = new(cradle.Connection)('http://127.0.0.1', 5984, {
auth: { username: 'toto_finish', password: 'password' }
});
var db = connection.database('test');
db.save('exercise', {
FullName: param_name, Age: param_age
}, function (err, res) {
if (err) {
// Handle error
response += ' SAVE ERROR: Could not save record!!\n';
} else {
// Handle success
response += ' SUCESSFUL SAVE: The record was saved in CouchDB!\n';
}
http_res.end(response);
});
this code works well and it saves the data to the CouchDB.
My problem is when I want to read the data.
The code that I wrote is:
var cradle = require('cradle');
var connection = new(cradle.Connection)('http://127.0.0.1', 5984, {
auth: { username: 'toto_finish', password: 'password' }
});
var db = connection.database('test');
db.view('exercise/all', {descending: true}, function(err, res)
{
console.log(res);
res.forEach(function (row) {
response = 'FullName: ' + row.FullName + '\n Age: ' + row.Age + '\n';
});
});
http_res.end(response);
when I am trying to print response, response is empty and I don't know what I am doing wrong. I know that it does not go inside the forEach loop but I don't understand why.
the console output is:
[ { id: 'exercise',
key: null,
value:
{ _id: 'exercise',
_rev: '1-7042e6f49a3156d2099e8ccb3cc7d937',
FullName: 'Toto Finish',
Age: '30' } } ]
Thanks in advance for any response or answer.

Try moving the http_res.send() call inside the callback provided to db.view - the anonymous function( err, res ) { }.
I'm not sure however about the .forEach statement, you'll only get the last value from your query in the response variable, you should look into that as well.

spotirca is right
The db.view function is async so http_res.end(response) gets called before the view returns any data.
You can prove this by returning the date in both the console.log and http_res.end
console.log(res, new Date())
and
http_res.end(response, new Date());
The http response will have the earlier date/Time.

Related

Can't retrieve embedded object from a MongoDB document - MERN stack

I am using the MERN stack for my current project. So I am facing this problem:
Let's say that I have the following document in MongoDB :
{
name: "Tesla Inc.",
category: "Automotive",
contact: {
state : {
name: "Texas",
city: "Austin",
address: {
streetName: "Tesla Road",
number: '1'
}
}
}
}
What I get as response after using findOne({ name : "Tesla"}) is :
{_id: '637e4397f6723844191aa03d', name: 'Tesla', category:
'Automotive', contact: {…}}
As you can see contact object is undefined
Follows my coding process
This is my Express route for quering the database :
storeRoutes.route("/enterprise").get(function (req, res) {
let db_connect = dbo.getDb("res");
const query = { name : "Tesla"};
db_connect
.collection("stores")
.findOne(query,function (err, result) {
if (err) throw err;
res.json(result);
});
});
Result: After typing browser url http://localhost:5000/enterprise returns the expected value:
{"_id":"637e4397f6723844191aa03d","name":"Tesla","category":"Automotive","contact":{"state":{"name":"Texas","city":"Austin","address":{"streetName":"Tesla Road","number":"1"}}}}
This a Retriever Data Function that returns the data object:
function GetEnterprise() {
const [store, setStore] = useState({
})
useEffect(() => {
async function fetchData() {
const response = await fetch(`http://localhost:5000/enterprise`);
if (!response.ok) {
const message = `An error has occurred: ${response.statusText}`;
window.alert(message);
return;
}
const record = await response.json();
if (!record) {
// window.alert(`Record with id ${id} not found`);
window.alert(`Record with id not found`);
return;
}
setStore(record);
}
fetchData();
return;
}, [1]);
//debugging
console.log('tesla: ' + store);
window.store = store;
let res_json = JSON.stringify(store);
console.log('res_json :' + res_json);
return store;
}
Result:
Before GetEnterprise() function returns store I have added these 4 lines of code for debugging:
console.log('tesla: ' + store);
window.store = store;
let res_json = JSON.stringify(store);
console.log('res_json :' + res_json);
1st line logs [object Object] which is not that informative for what I am getting back as a response.
So I came up with 2nd line which enables to debug directly from the browser console.
After I type store my console logs:
{_id: '637e4397f6723844191aa03d', name: 'Tesla', category: 'Automotive', contact: {…}}
So my contact object is missing(undefined).
Now fun fact is the 3rd and 4rd lines :
let res_json = JSON.stringify(store);
console.log('res_json :' + res_json);
My console logs the whole object as expected:
{"_id":"637e4397f6723844191aa03d","name":"Tesla","category":"Automotive","contact":{"state":{"name":"Texas","city":"Austin","address":{"streetName":"Tesla Road","number":"1"}}}}
Which is really weird.
I guess it has something to do with the async and await functions. But I am not sure.
What am I doing wrong?
Any suggestions ..?

Update Entire Collection In MongoDB Node Js

I have a program that receive a New file from FTP server after some specific time , I insert the new updated file's data into my database MongoDB the fields remain same , only data changes in new file.. Now the problem is that EVERY TIME I have to insert whole new collection into database, and the collection increases accordingly.Forexample- first time data is of 20 records , second time 40 and then 60 and so on .The thing I want to do is I want to check which field's data is updated in New file before inserting new FILE's data , and should only update these field's data in database instead of inserting whole new document.Does MONGOOSE or MONGODB provide solution for this , means IF I PASS A DATA AS PARAMETER , IT SOULD COMPARE MY EXISTING COLLECTION WITH MY NEW DATA and then Update Only UPDATED FIELDS ..Please help me i,m stuck , thanks :) . I,m using NODE JS ...
var c = new Client();
var connectionProperties = {
host: 'ABC',
user: 'ABC',
port: 'ABC',
password: 'ABC',
};
c.connect(connectionProperties);
c.on('ready', function () {
c.get('path-to-excel-file', function (err, stream) {
if (err) throw err;
stream.once('close', function () {
const workBook = XLSX.readFile('Convertedfile.xlsx');
XLSX.writeFile(workBook, 'Convertedfile', { bookType: "csv" });
csv()
.fromFile("Convertedfile")
.then((jsonObj) => {
Model.collection.insert(jsonObj, function (err, docs) {
if (err) {
return console.error(err);
} else {
console.log("All Documents insterted");
}
});
})
c.end()
});
stream.pipe(fs.createWriteStream('ConvertedFile.xlsx'))
})
})
It looks like you need upsert means update if document/record exists or insert/create it.
So this can be done either 1 document at a moment or in bulk, but it would need a query to find the matching document(s) first.
Since you've not provided any sample data so I can't write a sample code snippet for you but here is the link to get you started, for bulk: Bulk.find.upsert and for single document this thread is good : how-do-i-update-upsert-a-document-in-mongoose
Update: here is the mongodb bulk upsert in action:
const mongo = require('mongodb');
const MongoClient = mongo.MongoClient;
const client = new MongoClient('mongodb://127.0.0.1:27017', { useUnifiedTopology: true });
client.connect(async err => {
if (err) {
console.log('DB Connection Error ', err);
} else {
const db = client.db('node-cheat-db');
// lets assume you've read all file contents and data is now ready for db operation
let records = [
{first: 'john', last: 'doe', email: 'johen#doe.com'},
{first: 'jack', last: 'doe', email: 'jack#doe.com'},
{first: 'jill', last: 'doe_updated', email: 'jill#doe.com'}
];
// prepare bulk upsert so that new records are created and existing are updated
let bulk = db.collection('users').initializeOrderedBulkOp();
for (var i = 0; i < records.length; i++) {
bulk.find({
"email": records[i].email // at least 1 key should be treated as PK; in this example email is PK
}).upsert(records[i]).replaceOne(records[i]);
}
bulk.execute(function (err,updateResult) {
if (updateResult.result.ok != 1) {
console.log('Bulk Upsert Error');
} else {
console.log(`Inserted: ${updateResult.result.nUpserted} and Updated: ${updateResult.result.nModified}`);
}
});
}
});
sample output looks like:
Inserted: 0 and Updated: 3
Further Details:
Clone node-cheat bulk-update, run node bulk-update.js followed by npm install mongodb.

Error chain in NodeJs with sychronize

I wrote a function to create a user profile.
I use the synchronise module to get rid of the callback hell.
When I do this, everything works fine:
var sql = jsonSql.build({
type: 'insert',
table: 'tbl_user',
values: {firstname: data.firstname, lastname: data.lastname, email: data.email, website: data.website, password: data.hashedPassword},
});
try {
var query = sync.await(db.query(sql.query, sql.values, sync.defer()));
} catch (err) {
res.status(500).send(err);
return;
}
When sql finds a user with an already used mail address it sends an error. Perfect.
Then I thought it would be a good idea to separate the code where the user is written into the database, because maybe you want to create a user in the admin-backend and then I could reuse the smaller function.
The smaller function:
function createUserInDB(data) {
var sql = jsonSql.build({
type: 'insert',
table: 'tbl_user',
values: {firstname: data.firstname, lastname: data.lastname, email: data.email, website: data.website, password: data.hashedPassword},
});
return db.query(sql.query, sql.values);
}
Which now gets called from the main function:
try {
var query = sync.await(userService.createUserInDB(data, sync.defer()));
console.dir(query);
} catch(err) {
console.dir(err);
res.status(500).send(err);
return;
}
This does not work.
How can I get the result of the smaller function (as error or query result) in my main function, so I am able to use try / catch?
I finally solved it.
function createUserInDB(data, resolve) {
sync.fiber(function() {
data.hashedPassword = bcrypt.hashSync(data.password, 10);
var sql = jsonSql.build({
type: 'insert',
table: 'tbl_user',
values: {firstname: data.firstname, lastname: data.lastname, email: data.email, website: data.website, password: data.hashedPassword},
});
try {
var query = sync.await(db.query(sql.query, sql.values, sync.defer()));
//first argument would be error
resolve(null, query);
} catch(err) {
resolve(err);
}
});
}
Basically, add the callback function to the function parameter and then just resolve it inside the fiber.

how to fetch _id data in loopback

My Database is arangodb. What i want to do is : I have data like this:
_id:authModel/1209597
_key:1209597
{
email: 'abc#gmail.com',
password: 'password',
subuser_ids:[ '811289', '1209611' ],
id: '1209597'
}
_id:authModel/811289
_key:811289
{
email: 'pqr#gmail.com',
password: 'password',
id: '811289'
}
actually i need to fetch data which is the ids in subuser_ids array, ie the subuser_ids contain 2 ids. I need to fetch the data that the subuser_id hold. suppose subuser_id is "811289" that is _id="811289" i need to fetch that data. am using arangodb and loopback. also i write an remote method to accesss that data. What i have is :
model.js
var server = require("../../server/server");
module.exports = function (Authmodel) {
Authmodel.on("attached", function () {
Authmodel.getApp(function (err, app) {
Authmodel.getSubUsers = function (params, cb) {
var result = [];
params.forEach(function (id) {
app.models.authModel.findOne({ "_id": id }, function (err, r) {
console.log("err", err);
console.log("r", r);
result.push(r);
});
})
cb(null, result);
};
});
});
Authmodel.remoteMethod('getSubUsers', {
accepts: { arg: 'params', type: 'array' },
returns: { arg: 'result', type: 'array' }
});
};
i got the log in the result console but that data is not correct.
How can i solve this issue? i need to fetch all subuser_ids data. any help will really appreciable and helpfull.

Mongoose, geospatial query for users

I'm currently working with nodeJS, using express and mongoDB and mongoose for an ORM. When I create a User and save them to the database I would like to query their location and save it. This is what I am currently doing, I have a UserSchema and a location Schema.
My userSchema just has the location stored as a string and in the location Schema itself I have
var locationSchema = new mongoose.Schema({
name: String,
loc: {
type: [Number],
index: '2d'
}
});
mongoose.model('Location', LocationSchema);
And then in my controller, I have the following
import json from '../helpers/json;
import mongoose from 'mongoose';
var User = mongoose.model('User);
module.exports = function() {
var obj = {};
obj.create = function (req, res) {
var user = new User(req.body);
user.roles = ['authenticated']
user.location = getLocation(req);
user.save(function (err) {
if (err) {
return json.bad(err, res);
}
json.good({
record: user,
});
});
};
return obj;
function getLocation (req) {
var limit = req.query.limit || 10;
var maxDistance = req.query.distance || 1;
maxDistance /= 6371;
var coords = [];
coords[0] = req.query.longitude;
coords[1] = req.query.lattitude;
Location.findOne({
loc: {
$near: coords,
$maxDistance: maxDistance
}
}).limit(limit).exec(function (err, location) {
if (err) {
console.log(err);
}
return location.name;
});
}
};
I have also tried using location.find instead of findOne and returning locations[0].name.
The error is thrown says cast to the number failed for value undefined at loc.
Do I need to send the location data to the server from the client side? If so, is there a best method to implement this? I have heard of the HTML5 Geolocation API, but I have never utilized it.
Thank you!
!!! -- UPDATE --- !!
I have started using the Geolocation API on the client side to send this data to the server in the request. I am using angular on the client side like so
(function() {
'use strict';
angular.module('opinionated.authentication')
.controller('SignupController', SignupController);
/* #ngInject */
function SignupController ($state, appUsers, appToast) {
var vm = this;
vm.reset = reset;
vm.create = create;
vm.user = {
name: '',
username: '',
email: '',
password: ''
};
vm.location = {
lattitude: '',
longitude: ''
};
function create = (isValid) {
if (isValid) {
var user = new appUsers.single({
name: vm.user.name,
username: vm.user.username,
email: vm.user.email,
password: vm.user.password,
lattitude: vm.location.lattitude,
longitutde: vm.location.longitude
});
user.$save(function (response) {
if (response.success) {
appToast('Welcome to Opinionated, ' + response.res.record.name);
$state.go('authentication.wizard')
} else {
appToast(response.res.messsage);
}
});
} else {
appToast('Hmm... Something seems to be missing');
}
}
function getPosition() {
navigator.geolocation.getPosition(updatePosition);
}
function updatePosition (position) {
vm.location.lattitude = position.coords.lattitude;
vm.location.longitutde = position.coords.longitude;
}
getPosition();
....
I think it has something to do with how I am getting the coordinates now. My browser prompts me for permission to use my location, so I am at least requesting the data. However, I changed my User Schema to save the lat and long and neither of these values are being saved upon success.
I found my error. I did need to include the Geolocation API to get the users coordinates. I then just saved the coordinates to the database and am using mongo's geo service from there! Everything works fine now.

Resources