Couchdb using nano , how to write search query - couchdb

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.

Related

How to get the time value when an entity is updated/created in Google datastore?

I am creating entities in my node js server. My /message route creates the entity and my display-message route reads the entity data. Is there a way to check when an entity was created or updated? If not, is there another way to attach a time to the entity object? Basically I am using the time to check if the entity has been updated or not in the display-message route.
Message Route
app.post('/message', function (request, response) {
let message = request.body.Body;
response.send("<Response><Message>Heyyo!</Message></Response>");
let entity = {
key: key,
data: {
message: message
//send timestamp value information
}
};
datastore.upsert(entity)
.then(()=> {
});
});
Display-Message route
app.get('/display-message', function(req,res){
datastore.get(key)
.then(function(results) {
//read timestamp value information
let entity_data = results[0];
let message_text = entity_data.message;
});
});
There's no built-in support for creation/update time in Cloud Datastore entities, but you can always attach one in a property of your choice when you create/save the entity:
const entity = {
key: key,
data: {
message: message,
my_timestamp_property: new Date()
}
};
Be aware, though, that putting timestamps in an index (single properties are indexed by default) can lead to increased read and write latency. See the best practices article for more info.

Insert in a different table in Azure table script for Azure Mobile Apps

I've been searching extensively for this answer but only found solutions referring to the old Azure App Services instead of the new Azure Mobile Apps.
In this exemple, in the Table Scripts of a table, I'm inserting the authenticated user id into the userID field of that same table.
table.insert(function (context) {
context.item.userId = context.user.id;
return context.execute();
});
But if also want to insert it in a different table from the one the user has asked to insert? How can I access this other table from the Table Scripts?
Before, as shown on all solutions I found, you could do "tables.getTable('otherTable')" to access another table from the same SQL DB. But now I get an error.
Reading the 'Azure Mobile Apps - Node SDK' documentation, I found the "context.tables()" function, that appears to obtain a different table from the db. But when I insert using the code bellow nothing happens:
table.insert(function (context) {
var table2 = context.tables('table2');
table2.insert({string_column: '1234'});
return context.execute();
});
Thanks!
Found out the correct way of doing it. Here is my code:
var insertMiddleware = function(req,res,next){
var table2 = req.azureMobile.tables('table2');
var toBeInserted = {field1: 'something',
id: '1'}; //id is needed
var promiseReturned = table2.insert(toBeInserted);
promiseReturned.then(function(data){
console.log('Inserted with success!');
next();
}, function(error) {
console.log('Found an error', error);
});
};
table.insert.use(insertMiddleware, table.operation);
table.insert(function (context) {
return context.execute();
});
First I declare a middleware function that will be executed every time the insert is called. In it I call the insert function from the table I want to access, and it returns a promise. (that was my error)
Then I associate the middleware with the insert function of the table where the script is running using the "use" function.
Finally I run the insert function normally.
In my case I wanted to insert the a record into another table after the id was generated so I wrote it as part of the callback.
table.insert(function(context) {
return context.execute().then(function(results) {
var table2 = context.tables('table_name');
var newRecord = {
id: results.id,
some: "data",
more: "123"
};
table2.insert(newRecord);
return results;
});
});

Reject two in a row requests (nodejs)

Sometimes we need restrict executing repeating requests from a user if the first request has not been finished. For example: We do want register user at some service, and only after that put him into database with external id. I would like to have a service where I can set protected routes.
I have solved this problem by checking flag at request.start() -> and removed it after the request has been completed. Anyway I'm looking for your suggestion guys.
I think you need to build this into the route handlers yourself:
var inProgress = []
var handleRegisterRoute = function create(req, res, next) {
var id = req.user.id
var found = _.find(inProgress, function(item){
return item = id
})
if(found){
res.send('Dont think twice, its aright')
return
} else {
inProgress.push(id)
completeRegister()
inProgress= _.without(inProgress, id);
req.send()
return
}
}
Again this is psuedo code - to the gist of what I would write. You may need to store the "inprogress" in a better data store referenceable by your entire server farm - some sort of DB.

Meteor cannot retrieve data from MongoDB

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);
});

Temporary CouchDB View using Node module Nano

Nano doesn't provide documentation for temporary views, is there any undocumented method? Failing that, how would you advise somebody execute a temporary view using a nano-like syntax. Currently I am attempting to create the view as _view/guid, query it, return the results, and then delete it from the collection:
function generateToken() {
return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
}
var db = nano.use('db'),
fn = 'function(doc){ emit(doc); }',
token = generateToken(),
id = '_design/' + token;
db.insert({ views: { view: { map: fn } } }, id, function(){
db.view(token, 'view', function (err, results) {
db.get(id, function (err, view) {
console.log(results);
db.destroy(id, view._rev);
});
});
});
I assume this is inoptimal with the temporary view functionality built into couch core.
I'm aware of the temporary-view caveats, however I do believe I have a genuine usage case.
The temporary view API is described in the official CouchDB documentation: http://docs.couchdb.org/en/latest/api/database/temp-views.html#post--db-_temp_view
Open up futon and see what calls it does to the couchDB api ?
Edit: went and did the above
Futon does a post to SVRNAME/DBNAME/_temp_view?limit=11&descending=true
request payload {language: "javascript" map: function(doc) { emit(null, doc.id);}
and you must be logged in as an admin.
Hope that helps
I think you could do this through Nano using nano.request() (or nano.dinosaur()). https://github.com/dscape/nano#nanorequestopts-callback

Resources