CouchDB/Cloudant query view by key that is array? - couchdb

alice.view('characters', 'soldiers', {
'keys': ['Hearts', 'Clubs']
}, function(err, body) {
if (!err) {
body.rows.forEach(function(doc) {
console.log(doc.value);
});
}
});
Does this filter on key: "Heart" or key: "Clubs" or the exact match key: ["Hearts", "Clubs"]? I wish to do the latter where my keys are arrays with 2 items.
Also if I JUST inserted into the db, can I expect this view to immediately be up to date when I run that code?

the view() function above will filter on key: "Heart" or key: "Clubs".
instead, you may want to try using the startkey and endkey:
*DB_NAME*/_design/characters/_view/soldiers?startkey=["Hearts", "Clubs"]&endkey=["Hearts", "Clubs"]&inclusive_end=true
something, like this:
alice.view('characters', 'soldiers', {
'startkey': ['Hearts', 'Clubs'],
'endkey': ['Hearts', 'Clubs'],
'inclusive_end': true
}, function(err, body) {
if (!err) {
body.rows.forEach(function(doc) {
console.log(doc.value);
});
}
})
reference:
https://stackoverflow.com/a/42398481

Related

Get criteria not match the schema

Im trying to get an Item from DynamoDB based on Primary Key but it throws me an exception:
ValidationException: The provided key element does not match the schema
Here is how my table looks:
I'm following a tutorial and here is how I wrote my get:
let params = {
TableName: process.env.CALL_NAVEGATION_HISTORY_TABLE,
Key: {
"Id": requestBody.CallSid
}
}
dynamoDb.get(params, function(err, data) {
if(err){
console.log('Error on dynamodb', err);
callback(null, Helpers.xmlTwimlResponse(twiml));
}
console.log(data);
callback(null, Helpers.xmlTwimlResponse(twiml));
});
What is wrong on my code?
Sometimes the most obvious thing is what we miss right in front of our eyes.
let params = {
TableName: process.env.CALL_NAVEGATION_HISTORY_TABLE,
Key: {
"Id": requestBody.CallSid
}
}
The Key name is case-sensitive. If you change it to 'id' it should work fine.

DynamoDB scanning using filter

Im new to DynamoDB and have a table which is "feeds" and partition key is "id" and i have 3 other attributes which are "category", "description", "pubDate".
I want to query the "category" attribute. But it doesn't work, because i can only query the partition key (hashkey), if im right.
Now my query is that which doesnt work;
let category = event.category;
const params = {
Key: {
"category": {
S: category
}
},
TableName: "feeds"
};
dynamodb.getItem(params, function (err, data) {
if (err) {
console.log(err);
callback(err);
}
else {
console.log(data);
callback(null, data);
}
});
How can i make it work? I tried to write a scan query but i couldn't understand the documentation of AWS good.
Edit: I did make it work with the help of Dunedan. Here is the working code,
var params = {
TableName: 'feeds',
IndexName: 'category-index',
KeyConditionExpression: 'category = :category',
ExpressionAttributeValues: {
':category': 'backup',
}
};
var docClient = new AWS.DynamoDB.DocumentClient();
docClient.query(params, function(err, data) {
if (err) callback(err);
else callback(null, data);
});
If your application will regularly query for the category, you should check out Global Secondary Indexes (GSI), which allow you to generate a projection of your data with another key than the original hash key as the key you can use to query.
Scanning and filtering as you suggested doesn't scale very well, as it fetches all data in the table and just filters the results.

Returning raw entities from Azure Table Storage in Node.js

My JavaScript objects/entities look like this:
{
id: 1,
name: 'foo',
timestamp: new Date()
}
The entities I need to pass to the Azure TableService are going to look something like this:
{
id: { '_': 1, '$': 'Edm.Int32' },
name: { '_': 'foo', '$': 'Edm.String' },
timestamp:{ '_': new Date(), '$': 'Edm.DateTime' },
}
This is easily done using the entityGenerator and this is also the format in which the entities are returned from the TableService.
Is it possible though to return the raw values from the TableService when fetching data from a table?
I don't really need all of these OData types and metadata on my JavaScript objects.
I might need to use something like a PropertyResolver but the documentation is quite confusing.
How about trying with options parameter?
tableService.retrieveEntity(tableName, partitionKey, rowKey, {payloadFormat:"application/json;odata=nometadata"}, function(error, result, response) {});
It can be used also with queries:
tableService.queryEntities(tableName, query, null,{payloadFormat:"application/json;odata=nometadata"}, function(error,result, response) {});
And to get cleaner json you might take response.body instead result.
Example:
tableService.retrieveEntity(tableName, partitionKey, rowKey, {payloadFormat:"application/json;odata=nometadata"}, function(error, result, response) {
if (!error)
{
var myEntity = response.body;
}
});
You can use entityResolver to achieve this.
Example:
var entityResolver = function(entity) {
var resolvedEntity = {};
for(key in entity) {
resolvedEntity[key] = entity[key]._;
}
return resolvedEntity;
}
var options = {};
options.entityResolver = entityResolver;
tableSvc.retrieveEntity('mytable', 'hometasks', '1', options, function(error, result, response) {
if(!error) {
console.log('result: ', result);
}
});

Response from db is offset, not all results returned using map function

Why is offset: 1?
I'm expecting to see 2 rows in the response from Cloudant, as total_rows indicates, but its offset for some reason so only 1 row is present in response.
Console output:
{ total_rows: 2,
offset: 1,
rows:
[ { id: '1e0a2d30d18d95b9bcc05d92c883d496',
key: '1e0a2d30d18d95b9bcc05d92c883d496',
value: [Object] } ] }
Calling the function, handle response:
viewImpl('test', 'something').then(function(result) {
result.rows.forEach(function(doc) {
console.log(doc.value);
});
res.status(200).send('done');
}
}).catch(someFunc());
Function def:
App.prototype.viewImpl = function(designName, viewName) {
return new Promise(function(fulfill, reject) {
_this.db.view(designName, viewName, { keys: ["1e0a2d30d18d95b9bcc05d92c883d496","1e0ad30d18d95b9bcc05d92c883e272"] }, function(err, result) {
if (err) {
reject(err);
} else {
fulfill(result);
}
});
});
};
View defined in Cloudant:
function(doc) {
emit(doc._id, { _id: doc._id, _rev: doc._rev, some_field: doc.some_field });
}
Take a look at the keys provided to the view() function:
1e0a2d30d18d95b9bcc05d92c883d496
1e0ad30d18d95b9bcc05d92c883e272
The second key is one character shorter - it's just 31 characters instead of 32. I guess you just missed the last character when copy pasting it from document ID.
Remove the keys parameters to see all rows, then check what is the correct key for the second row and update your code.

Exclude fields from result in MongoDB monk

I want to exclude some fields from result.
I have code:
users = db.select('users');
users.find( {}, { sort: { points:1 }, privateKey:0, publicKey:0}, function(err,data){
res.send(data);
});
I want to exclude private and public key from results.
Can I do that using monk?
You can also do it like this:
users.find( {}, { sort: { points:1 }, fields : { privateKey:0, publicKey:0} },
function(err,data){
res.send(data);
}
);
According to documentation first argument in find is filter and second is projection .But you have used sort . It will not able to interpret . You are trying to confuse projection with sort .Sorting should be after find and projection.
You can write projection like { field1: <boolean>, field2: <boolean> ... }
Note :
The find() method always includes the _id field even if the field is not explicitly stated to return in the projection parameter.
users.find({}, { privateKey: 0, publicKey: 0 }).sort({points: 1}).toArray(
function (err, data) {
res.send(data);
});
For me, I need to use the .project() method:
const someFunction = async () => {
const result = await users
.find({}, { sort: { points: 1 })
.project({ privateKey: 0, publicKey: 0});
};
This is what worked for me for excluding the _id field.
const courseChapters = await db
.collection("users")
.find({}, { projection: { _id: 0 } })
.toArray();
So the example in the question would look something like this.
users.find(
{},
{ projection: { points: 1, privateKey: 0, publicKey: 0 } },
function (err, data) {
res.send(data);
}
);
Check out this other answer that says you may need the fields field instead of projection depending upon your driver

Resources