Using design documents in pouchDB with crypto-pouch - ionic-framework

After testing pouchDB for my Ionic project, I tried to encrypt my data with crypto-pouch. But I have a problem with using design documents. I used the following code:
One of my design documents:
var allTypeOne = {
_id: '_design/all_TypeOne',
views: {
'alle_TypeOne': {
map: function (doc) {
if (doc.type === 'type_one') {
emit(doc._id);
}
}.toString()
}
}
};
For init my database:
function initDB() {
_db = new PouchDB('myDatabase', {adapter: 'websql'});
if (!_db.adapter) {
_db = new PouchDB('myDatabase');
}
return _db.crypto(password)
.then(function(){
return _db;
});
// add a design document
_db.put(allTypeOne).then(function (info) {
}).catch(function (err) {
}
}
To get all documents of type_one:
function getAllData {
if (!_data) {
return $q.when(_db.query('all_TypeOne', { include_docs: true}))
.then(function(docs) {
_data = docs.rows.map(function(row) {
return row.doc;
});
_db.changes({ live: true, since: 'now', include_docs: true})
.on('change', onDatabaseChange);
return _data;
});
} else {
return $q.when(_data);
}
}
This code works without using crypto-pouch well, but if I insert the _db.crypto(...) no data is shown in my list. Can anyone help me? Thanks in advance!

I'm guessing that your put is happening before the call to crypto has finished. Remember, javascript is asynchronous. So wait for the crypto call to finish before putting your design doc. And then use a callback to access your database after it's all finished. Something like the following:
function initDB(options) {
_db = new PouchDB('myDatabase', {adapter: 'websql'});
if (!_db.adapter) {
_db = new PouchDB('myDatabase');
}
_db.crypto(password)
.then(function(){
// add a design document
_db.put(allTypeOne).then(function (info) {
options.success(_db);
})
.catch(function (err) { console.error(err); options.error(err)})
.catch(function (err) { console.error(err); options.error(err);})
}
}
initDB({
success:function(db){
db.query....
}
)

Related

How to check if value already exists in the data received from api before inserting it into db

I am having hard times trying to write data received from a api to db.
I successfully got data and then have to write it to db. The point is to check whether the quote is already exists in my collection.
The problem I am dealing with is that every value gets inserted in my collection, not regarding if it exists or not.
const { MongoClient } = require('mongodb')
const mongoUrl = 'mongodb://localhost/kanye_quotes'
async function connectToDb() {
const client = new MongoClient(mongoUrl, { useNewUrlParser: true })
await client.connect()
db = client.db()
}
async function addQuote(data) {
await connectToDb()
try {
const collection = db.collection('quotes')
let quotes = [];
quotes = await collection.find({}).toArray()
if (quotes = []) { // I added this piece of code because if not check for [], no values will be inserted
collection.insertOne(data, (err, result) => {
if (err) {
return
}
console.log(result.insertedId);
return
})
}
quotes.forEach(quote => {
if (quote.quote !== data.quote) { // I compare received data with data in collection, it actually works fine(the comparison works as it supposed to)
collection.insertOne(data, (err, result) => {
if (err) {
return
}
console.log(result.insertedId);
})
} else console.log('repeated value found'); // repeated value gets inserted. Why?
})
}
catch (err) {
console.log(err)
}
}
Hi it's probably better to set unique: true indexing on your schema. That way you won't have duplicated values.

Calling mongodb insert,find functions from another class in react native , returns undefined

This is my first class where I defined all db functions.
import React,{Component} from 'react';
var Datastore = require('react-native-local-mongodb')
, db = new Datastore({ filename: 'asyncStorageKey', autoload: true });
export default class RDDBManager {
static dbmanager = null;
static getInstance() {
if (RDDBManager.dbmanager == null) {
RDDBManager.dbmanager = new RDDBManager();
}
return this.dbmanager;
}
constructor () {
}
//insert items
insertItem(item){
var json = item.toJsonString();
console.log("Inside insertItem ::: "+json);
db.insert(json,function(err,newDos){
return newDos;
});
}
//read single item
readItem(itemId){
db.findOne({ id: itemId }, function (err, doc) {
return doc;
});
}
//read all items
readAllItems(){
db.find({}, function (err, docs) {
return docs;
});
}
getModalData(modalName) {
this.readAllItems();
}
//update
updateItem(itemId){
db.update({ id: itemId }, { $set: { system: 'solar system' } }, { multi: true }, function (err, numReplaced) {
});
}
//delete item
deleteItem(itemId){
db.remove({ id: itemId }, {}, function (err, numRemoved) {
return numRemoved;
});
}
}
But,when I try to call these functions from another class,the data is undefined.
loadDataFromDB() {
var items = RDDBManager.getInstance().readAllItems();
console.log("Items ======>>>>>> "+items);
}
the value of items is undefined.
This is because you are not doing things right, Your readallitems is async in nature so you have to do something like this:-
//read all items
readAllItems(callback){
db.find({}, function (err, docs) {
callback(docs);
});
}
And For calling something like this:-
loadDataFromDB() {
RDDBManager.getInstance().readAllItems(function(items){
console.log("Items ======>>>>>> "+items);
});
}
Alternatively, you can use promise or Async await also.

Waterline ORM assign the result of find to a variable

I want to combine the results of 2 queries and then return them as one, like this:
test: async (req, res) => {
const valOne = TableOne.find({ id: id })
.exec((err, result) => {
if (err) {
res.serverError(err);
}
return result;
});
const valTwo = TableTwo.find({ id: id })
.exec((err, result) => {
if (err) {
res.serverError(err);
}
return result;
});
const data = {
keyOne: valOne,
keyTwo: valTwo,
};
res.json(data);
}
I understand above code won't return because it's async. How can I achieve this?
There is not much info you supply: node version, sails version, etc.
There are several approaches here:
1. Using promises
2. Using callback chaining
3. Using await/async
If you use sails 1.0 and node >= 8, your best bet is to use await/async, so your code should work like that:
test: async (req, res) => {
let valOne, valTwo;
try {
valOne = await TableOne.find({ id: id });
valTwo = await TableTwo.find({ id: id });
} catch (err) {
return res.serverError(err); //or res.badRequest(err);
}
const data = {
keyOne: valOne,
keyTwo: valTwo,
};
res.json(data);
}

How to update a model with Sails JS

Ok, I've got the following in one of my controllers:
User.find({email: 'email#example.com'}).then(function (user) {
user[0].field = 'new_value';
user[0].field_2 = 'new_value';
console.log(user[0], 'before saving');
user[0].save();
console.log(user[0], 'after saving');
});
If I console user[0] at this stage I can see the updated fields. However the changes were not saved to the db. If I do the following:
User.find({email: 'email#example.com'}).then(function (user) {
user[0].field = 'new_value';
user[0].field_2 = 'new_value';
user[0].save();
User.find(user[0].id).then(function (updateduser) {
console.log(updateduser[0])
});
});
The updateduser does not have the updated fields... Why is that? How can should I proceed in this case?
Actually
user[0].save();
will return a promise like you have done for User.find().then();
user[0].save() is an asynchronous call so the next call to find the user will run even though the user[0] is not updated in the database.
so place the second find command inside the then of save() function and you will get the updated user.
user[0].save().then(function(err){
User.find(user[0].id).then(function (updateduser) {
console.log(updateduser[0])
});
}))
Why you not use updated() method?
User.find({ email: 'email#example.com' })
.then(function(user) {
if (!user) return res.notFound();
User.update({ eamil: 'eamil#example.com' }, {
field: 'new_value',
field_2: 'new_value'
})
.then(function(updated_user) {
console.log(updated_user);
return res.ok();
})
.catch(function(err) {
sails.log.error(err);
return res.serverError();
});
})
.catch(function(err) {
sails.log.error(err);
return res.serverError();
});
First of all, you want to update only one user data because you are using user[0](I think).
So it is easy to use findOne().
Simple code
User
.findOne({email: 'email#example.com'})
.exec(function(err,user){
if(err || !user) {
//handle here
}
else {
user.key1 = 'new_value';
user.key2 = 'new_value';
user.save(function(err){
if(err){
//handle error
}
console.log('updatedUser',user)
})
}
})
Thank you.

nightwatch custom command callback

I'm trying to create a custom command in nightwatch that runs a query on a Postgres database and returns the result. The query runs just fine and outputs the result to the console but then the execution of the test stops. I don't understand how callbacks work. How can I fix this custom command?
exports.command = function(sql, callback) {
var self = this;
var pg = require('pg');
var conString = self.globals.testinfo.connectionString;
var db = new pg.Client(conString);
db.connect(function(err) {
if(err) {
console.error('could not connect', err);
}
else {
db.query(sql, function(err, result) {
if(err) {
console.log('error running query', err);
}
else {
console.log(result.rows.length);
db.end();
}
});
}
}),
function(result) {
if (typeof callback === 'function') {
callback.call(self, result);
}
}
return this;
};
I had to wrap the database connection in a perform command to get this working. I'm not sure if this is the best way to handle the callback, but it works. Here's the updated version of the custom command:
exports.command = function(sql,callback) {
var self = this;
var pg = require('pg');
var cs = self.globals.testinfo.connectionString;
self.perform(function(self,done) {
pg.connect(cs,function(err,db,done) {
if(err) {
return console.error(err);
}
db.query(sql, function(err,result) {
done();
if(err) {
return console.error(err);
}
console.log(result.rows.length);
callback(result.rows[0]);
});
});
pg.end();
done();
});
};
Here's how I call the custom command in the test:
browser.myCustomCommand('select * from table limit 1;', function(row) {
browser.assert.deepEqual(row.column,'some value');
});
Can you try this:
exports.command = function(sql, callback) {
var self = this;
var pg = require('pg');
var conString = self.globals.testinfo.connectionString;
var db = new pg.Client(conString);
var cb= function(result) {
if (typeof callback === 'function') {
callback.call(self, result);
}
};
db.connect(function(err) {
if(err) {
console.error('could not connect', err);
cb(false);
}
else {
db.query(sql, function(err, result) {
if(err) {
console.log('error running query', err);
cb(false);
}
else {
console.log(result.rows.length);
db.end();
cb(true);
}
});
}
}),
return this;
};
And in your test :
'test' : function(browser){
browser.yourCommandName(sql,function(result){
console.log(result); //if connect is good result would be true and false if fail to connect.
});
}
Ps: the result in callback can be as an object(contain rows or anything you want), instead of boolean only in this example.
And Nightwatch is used for end-to-end testing, it is not aimed for Database testing,i think you should find another framework to test database connection.