Meteor cannot retrieve data from MongoDB - node.js

Pretty straightforward and without any sort of configuration ->
In the project directory I entered the command:
$ meteor mongo to access the mongodb
From there (mongo shell), I switched to db meteor using the command use meteor then entered some basic data to test:
j = { name: "mongo" }
k = { x: 3 }
db.testData.insert(j)
db.testData.insert(k)
I checked and got results by entering: db.testData.find()
Here's my meteor code provided that mongodb access is only required on the client:
if (Meteor.isClient) {
Template.hello.greeting = function () {
return "Welcome to test.";
};
Template.hello.events({
'click input' : function () {
// template data, if any, is available in 'this'
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
});
Documents = new Meteor.Collection('testData');
var document = Documents.find();
console.log(document);
var documentCbResults = Documents.find(function(err, items) {
console.log(err);
console.log(items);
});
}
Upon checking on the browser and based on the logs, it says undefined. I was unsuccessful from retrieving data from mongodb and showing to the client console.
What am I missing?

For this answer I'm going to assume this is a newly created project with autopublish still on.
As Christian pointed out, you need to define Documents on both the client and the server. You can easily accomplish this by just putting the collection definition at the top of the file or in another file which isn't in either of the server or client directories.
An example which prints the first two test documents could look like this:
Documents = new Meteor.Collection('testData');
if (Meteor.isClient) {
Template.hello.greeting = function () {
return "Welcome to apui.";
};
Template.hello.events({
'click input' : function () {
var documents = Documents.find().fetch();
console.log(documents[0]);
console.log(documents[1]);
}
});
}
Note the following:
The find function returns a cursor. This is often all you want when writing template code. However, in this case we need direct access to the documents to print them so I used fetch on the cursor. See the documentation for more details.
When you first start the client, the server will read the contents of the defined collections and sync all documents (if you have autopublish on) to the client's local minimongo database. I placed the find inside of the click event to hide that sync time. In your code, the find would have executed the instant the client started and the data probably would not have arrived in time.
Your method of inserting initial items into the database works (you don't need the use meteor by the way), however mongo will default to using an ObjectId instead of a string as the _id. There are subtle ways that this can be annoying in a meteor project, so my recommendation is to let meteor insert your data if at all possible. Here is some code that will ensure the testData collection has some documents:
if (Meteor.isServer) {
Meteor.startup(function() {
if (Documents.find().count() === 0) {
console.log('inserting test data');
Documents.insert({name: "mongo"});
Documents.insert({x: 3});
}
});
}
Note this will only execute if the collection has no documents in it. If you ever want to clear out the collection you can do so via the mongo console. Alternatively you can drop the whole database with:
$ meteor reset

It's not enough to only define collections on the client side. Your mongo db lives on the server and your client needs to get its data from somewhere. It doesn't get it directly from mongodb (I think), but gets it via syncing with the collections on the server.
Just define the Documents collection in the joint scope of client and server. You may also need to wait for the subscription to Documents to complete before you can expect content. So safer is:
Meteor.subscribe('testData', function() {
var document = Documents.find();
console.log(document);
});

Related

Unable to make PUT request to Cloudant-bluemix database using Nodejs-express

I'm trying to implement a Password reset. So I'm taking the phone number of the user, getting the document from the database using the phone number to find it, and I'm taking the new password and trying to update the corresponding document using a PUT request in my Cloudant database.
app.post('/pass_rst', function(req,response){
var log='';
//log is just for me to see what's happening
var phone= req.body.phone;
log+=phone+'\n';
db.find({selector:{'phone':phone}}, function(err, result){
if(err){
throw err;
}
if(result.docs.length==0){
response.send('User doesnt exist');
}else{
var existing_data=result.docs[0];
log+=JSON.stringify(existing_data)+'\n';
var upd_pswd= req.body.new_password;
log+=upd_pswd+'\n';
var new_data=existing_data;
new_data.password=upd_pswd;
log+=JSON.stringify(new_data)+'\n';
var id= result.docs[0]._id;
log+=id+'\n';
//make PUT request to db
var options={
host:dbCredentials.host,
port:dbCredentials.port,
path:'/'+dbCredentials.dbName+'/'+id,
//url: dbCredentials.url+'/'+dbCredentials.dbName+'/'+id,
method:'PUT',
json:new_data,
headers:{
'Content-Type':'application/json',
'accept':'*/*'
}
};
log+=JSON.stringify(options)+'\n';
var httpreq= http.request(options);
//log+=JSON.stringify(httpreq);
httpreq.on('error', function(e){
response.send('Error'+e.message);
});
response.send(log+'\n\n\nUpdated');
}
});
});
dbCredentials is defined above as follows:
dbCredentials.host = vcapServices.cloudantNoSQLDB[0].credentials.host;
dbCredentials.port = vcapServices.cloudantNoSQLDB[0].credentials.port;
dbCredentials.user = vcapServices.cloudantNoSQLDB[0].credentials.username;
dbCredentials.password = vcapServices.cloudantNoSQLDB[0].credentials.password;
dbCredentials.url = vcapServices.cloudantNoSQLDB[0].credentials.url;
I've tried tinkering around with it, but in the best case scenario, I don't get an error and I see "Updated" but nothing actually happens in the database. Sometimes I get an error saying : 502 Bad Gateway: Registered endpoint failed to handle the request.
If you see what's going wrong, please let me know. Thank you.
This is the documentation on how to update documents in cloudant
UPDATE
Updating a document
PUT /$DATABASE/$DOCUMENT_ID HTTP/1.1 { "_id": "apple", "_rev":
"1-2902191555", "item": "Malus domestica", "prices": {
"Fresh Mart": 1.59,
"Price Max": 5.99,
"Apples Express": 0.79,
"Gentlefop's Shackmart": 0.49 } }
To update (or create) a document, make a PUT request with the updated
JSON content and the latest _rev value (not needed for creating new
documents) to https://$USERNAME.cloudant.com/$DATABASE/$DOCUMENT_ID.
If you fail to provide the latest _rev, Cloudant responds with a 409
error. This error prevents you overwriting data changed by other
processes. If the write quorum cannot be met, a 202 response is
returned.
Example response: { "ok":true, "id":"apple",
"rev":"2-9176459034" }
The response contains the ID and the new revision of the document or
an error message in case the update failed.
I am using bluemix -nodejs and cloudant. The best way that worked for me to do the update is to use the nano package for db interaction from node.js.
You can refer to the post here:
The summary is - By making use of nano api, you can easily update the record. You need to make sure to use - the _id and the right _rev number, while you use nano. This inturn uses PUT Method underneath.
Updating and Deleting documents using NodeJS on Cloudant DB
When you are including nano, make sure to update the package.json to have the nano dependency added. Let me know if you have further questions on the update/delete
When using the cloudant node.js module there is no separate update function.
You need to use the db.insert function also for the update with the right doc revision, so you need to read the latest revision before the insert.
https://github.com/apache/couchdb-nano#document-functions
"and also used to update an existing document, by including the _rev token in the document being saved:"
// read existing document from db
db.get(key, function(error, existing) {
if (!error)
// use revision of existing doc for new doc to update
obj._rev = existing._rev;
// call db insert
db.insert(obj, key, cb);
});

Couchdb using nano , how to write search query

I am facing problem using couchdb. I am using nano module for this in nodejs. How can I implement search like match for user name and password. I tried this
body.rows.forEach(function(row) {
if(row.doc._id==user_id && row.doc.password==password){
found = true;
data = row;
}
});
but this is slow process
I found solution for search using key value in couch db using nano.
First you have to create design document and view (and implement
logic in that) then use them.
exports.testwhere = function (req, res) {
var db = nano.use('ionic');
db.insert({
"views": {
"by_email_and_password": {
"map": function (doc) {
emit([doc.email, doc.password], doc);
}
}
}
}, '_design/users', function (error, response) {
console.log("yay");
});
}
exports.testsearch = function (req, res) {
var db =
nano.use('ionic');
db.view('users', 'by_email_and_password', {
key: ["a#g.com", "aaa123"], include_docs: true
}, function (err, res) {
if (!err) {
console.log("Result " + JSON.stringify(res));
}
else {
console.log(err);
}
});
}
Your code body.rows.forEach ... is a map function (it iterates over every row) which executes a filter function if(row.doc._id==user_id ... to a row. Thats what CouchDB views do - exactly the same.
but this is slow process
True. Because of that CouchDB creates an index (a B-Tree that is a file inside CouchDB's database directory) and keeps this index up-to-date. The performance advantage for every request is that the result will be taken from the already prepared index instead of a just-in-time calculation as in your example.
The CouchDB view map function could look like:
function(doc) {
emit([doc._id,doc.password], null)
}
The key of every row is [:username,:password] and the value is null. If you request
/:db/:ddoc/_view/:name?key=[":username",":password"]
you will get the row immediately. Append a &include_docs=true and you will also get the whole doc appended to the row (alternatively you could emit a partial of the doc as value instead of null)
handling user accounts in CouchDB
User accounts and especially passwords are confidential data. CouchDB has the built-in _users db for it. I will not go into the details of the access control specifics of that db but want to say Store user account data there!. If you need account data outside this db then interpret that docs as "public profiles" e.g. to let users discover and connect to each other.

Using Node.js & NForce, Retrieve Records on Startup

I am attempting to modify this code:
https://github.com/jeffdonthemic/node-streaming-socketio/blob/master/app.js
So that as well as setting up the streaming, on startup it also performs a query to retrieve some records which are displayed to the user. I am attempting to place code like so:
var q = 'SELECT Id, Name, CreatedDate, BillingCity FROM Account';
sfdc.query({ query: q }, function(err, resp){
if(!err && resp.records) {
// do something with record, display to client
}
});
After the connection and ouath have been set up, however, I am unsure where to place that code in the lifecycle of the main application (app.js). Also, I am unsure how to pass this record once I have it so that it can be displayed on the client side. I keep getting this error when placing this code at various places in app.js:
TypeError: Cannot read property 'instance_url' of undefined

waiting for data to appear/change in DB

I am writing REST api which has to provide kind of real-time communication between users. Lets say I have db.orders collection. And I have api GET /order/{id}. This api should wait for some change in order document. For example it should return some data only when order.status is ready. I know how to do long-polling but I no idea how to check for data to appear/change in db. It would be easy if there was one app instance - then I could do this in memory, something like this:
var queue = []
// GET /order/{id}
function(req,res,next) {
var data = getDataFromDb();
if(data && data.status == 'ready') {
res.send(data);
return;
}
queue.push({id: req.params.id, req: req, res: res, next: next});
}
// POST /order/{id}
function(req,res,next) {
req.params.data.status = 'ready'
saveToDb(req.params.data);
var item = findInQueue(queue,req.params.id);
if(item) item.res.send(req.params.data);
}
First handler waits for data to have status ready and second sets status of data to ready. Its just a pseudocode and many things are missing (timeout for example).
The problem is when I want to use many instances of such app - I need some messaging mechanism which will allow to communicate across instances in kind of real time.
I read about REDIS PUB/SUB but I am not sure if I can use it in this way...
I am using node.js + restify + mongoDB for now.
You are looking for the oplog. It's a special capped collection where all operations on the database are stored. To enable them on a single server you can do.
mongod --dbpath=./data --oplogSize=100 --replSet test
then connect to the server using the console and write
rs.initiate()
use the console and do
use local
show collections
Notice the collection oplog.rs. it contains all the operations that have been applied to the server. If you are using node.js you can listen to the changes in the following way
var local = db.db("local");
var steam = local.collection("oplog.rs").find({}, {tailable:true, awaitdata:true}).stream();
stream.on('data', function(doc) {
});
for each operation on mongodb you'll receive a doc where you can establish if something you are interested in changed state.

Inserting data to MongoDB - no error, no insert

I'm currently trying to make a register form using mongoDB and nodeJS - I've created new database and collection - I want to store: username, password, email and insert_time in my database.
I've added unique indexes to username/email and checked if it works - and I can not add a duplicated entry using mongo's console or rockmongo (php mongodb manager) - so it works fine.
However - when the piece of code that is supposed to register a new account is being executed and makes an insert with the data that is already in database - it returns an object that contains all the data that was supposed to be added with a new, unique id. The point is - it should return an error that would say that entries can not be duplicated and insert failed - instead it returns the data back and gives it a new id. Data that already resides in database remains untouched - even the ID stays the same - it's not rewritten with the new one returned by script's insert.
So, the question is... what am I doing wrong? Or maybe everything is fine and database's insert should return data even if it's failed?...
I even tried defining indexes before executing indexes.
I tried inserting the data using mongoDB's default functions and mongoJS functions - the result is the same in both cases.
The code I'm trying to execute (for mongoJS):
var dbconn = require("mongojs").connect('127.0.0.1:27017/db', ['users']);
var register = function(everyone, params, callback)
{
// TODO: validation
dbconn.users.ensureIndex({username:1},{unique:true});
dbconn.users.ensureIndex({email:1},{unique:true});
dbconn.users.save(
{
username: params.username,
password: params.password,
email: params.email,
insert_time: Date.now()
},
function(error, saved)
{
if(error || !saved)
{
callback(false);
}
else
{
console.log(error);
console.log(saved);
callback(true);
}
});
}
For both cases - inserting new data and inserting duplicated data that doesn't modify database in any way - ERROR is null and SAVED is just a copy of data that is supposed to be inserted. Is there any way to check if insert was made or not - or do I have to check whether the data already exists in database or not manually before/after making an insert?
Mongo works that way. You should tell you want to get errors back, using the safe option when you issue the save command (as per default it uses the "fire and forget" method).
https://docs.mongodb.com/manual/reference/command/getLastError/
This looks to be basically the same problem as MongoDB unique index does not work -- but with the JavaScript API rather than Java. That is, saving without either specifying the "safe" flag or explicitly checking the last error value is unsafe--- the ID is generated client side and the command dispatched, but it might still fail (e.g. due to a unique index violation). You need to explicitly get the last error status.
http://www.mongodb.org/display/DOCS/dbshell+Reference#dbshellReference-ErrorChecking suggests db.getLastError() using the command shell, and I assume the node API is identical where they can possibly make it so.
Same problem solved, just forgot that its async insert and any nodes process.exit stops adding data
var lineReader = require('readline').createInterface({
input: require('fs').createReadStream('parse.txt')
});
lineReader.on('line', function (line) {
console.log(line)
db.insert(line,{w:1},function(e,d){ if (e) throw e })
});
// f this s, data are still adding when do close KUR WA MAC 2 days of my f life wasted
lineReader.on('close', function() {
// ----->>>>>> process.exit(); <<<<<----------
});

Resources