Lets suppose we store cars (about 40MB) represented as JSON objects in a PouchDB, and we would like to search, based on the horsepower attribute. example in sql: select * from cars where HP > 100.
You can query pouchDB by key, but obviously HP is not the key of the document. Is there a way you can do this?
As far as I understand the map function,
function(doc) {
if(doc.value) {
emit(doc.value, null);
}
}
it is not possible to access any variable within the outer scope of the function.
var horsePower = $scope.horsePowerInputField
function(doc) {
if(doc.hp > horsePower) {
emit(doc.value, null);
}
}
so is there a possibility to query the database, parametrized based on non-key variables?
As of PouchDB 2.0.0, closures in map/reduce queries are supported. Details here.
However, you should probably avoid them if you can, because
That being said, if you do want to use closures, you can now do this:
var horsePower = $scope.horsePowerInputField
function(doc, emit) { // extra 'emit' tells PouchDB to allow closures
if(doc.hp > horsePower) {
emit(doc.value, null);
}
}
Your map
function loses its closure because it is re-evaluated inside of PouchDB (that's how it gets the emit
function). This means you can't access any variables from your code, but you can still query the database.
In PouchDB, views are not persistent, so your query always looks at every document in the database, and you have to do the filtering after the map function. Something like this:
function findCars(horsePower, callback) {
// emit car documents
function map(doc) {
if(doc.type == 'car' && doc.value) {
emit(doc.value, null);
}
}
// filter results
function filter(err, response) {
if (err) return callback(err);
var matches = [];
response.rows.forEach(function(car) {
if (car.hp == horsePower) {
matches.push(car);
}
});
callback(null, matches);
}
// kick off the PouchDB query with the map & filter functions above
db.query({map: map}, {reduce: false}, filter)
}
Is one way to solve this problem. Pouch will iterate over each document, passing it to your map
function. When done, filter
gets called with an array of all the emitted documents. filter
does not lose its closure context, so you can filter the results based on horsepower or any other field here.
It's better not to use closures. Do this instead:
var horsePower = $scope.horsePowerInputField;
db.query(function(doc) {emit(doc.hp)}, {startkey: horsePower, include_docs: true});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With