Couchdb view search by numeric key - couchdb

I have couchdb setup to have documents like below
{
"_id": "id",
"_rev": "rev",
"docType": "CLAIM",
"createDate": 1633074806,
"customerClaimNumber": "CCN101",
"claimID": "CLID101"
}
Requirement is to have claims returned (claim id and customerclaim number) based on the createDate between start of day to end of day. CreateDate is epoch timestamp (an integer)
I have written the below view
function (doc) {
if(doc.docType =="CLAIM" && doc.claimDate && doc.customerClaimNumber) {
emit([doc.claimDate], doc.customerClaimNumber, doc.claimID);
}
}
I am looking at the recommendation to achieve search based on the createDate field (integer)

Well eventually i got this done by creating the view as
function (doc) {
if(doc.docType =="CLAIM" && doc.claimDate && doc.customerClaimNumber) {
emit(doc.claimDate, {vendorClaimNumber: doc.customerClaimNumber, blockchainClaimID: doc.claimID});
}
}
and then calling the view
_view/viewname?startkey=1600000212&endkey=1600010212

Related

CouchDB/PouchDB design documents query with startkey endkey not working

In my database I have (not only) two types of documents in a one-to-many relationship. I tried to manage this like the following example shows:
{
_id : "class:xyz"
type: "class"
... other keys ...
}
{
_id : "class:xyz:pupil:abc"
type: "pupil"
... other keys ...
}
If I query my docs with allDocs() like
http://url_of_my_server:5984/my_database/_all_docs?include_docs=true&?startkey="class:xyz:pupil:"&endkey="class:xyz:pupil:\ufff0"
I get all docs of type pupil related to the mentioned doc of type class like wanted.
For performance I had the idea to introduce a design document to query only the docs of type pupil and not all docs every time:
{
"_id": "_design/types",
"language": "javascript",
"views": {
"classes": {
"map": "function(doc){ if(doc.type == \"class\"){emit(doc.id, doc);} }"
},
"pupils": {
"map": "function(doc){ if(doc.type == \"pupil\"){emit(doc.id, doc);} }"
},
}
}
But if I query with this design document like
http://url_of_my_server:5984/my_database/_design/types/_view/pupils?include_docs=true&?startkey="class:xyz:pupil:"&endkey="class:xyz:pupil:\ufff0"
I get no result (only an empty array/no rows).
Where is my mistake or what is wrong in my conception? I actually have no idea? Thanks in advance for your advice.
First, for a view never emit the document as a value; it is quite redundant since one may use include_docs=true - and worse, it consumes storage unnecessarily.
Assuming two documents
{
_id : "class:xyz:pupil:abc"
type: "pupil"
},
{
_id : "class:xyz:pupil:xyz"
type: "pupil"
}
And the map function for pupils
"pupils": {
"map": "function(doc){ if(doc.type == \"pupil\"){emit(doc.id, doc);} }"
}
The view index for pupils looks like this
id
key
value
class:xyz:pupil:abc
null
{"_id": "class:xyz:pupil:abc", /* etc */ }
class:xyz:pupil:xyz
null
{"_id": "class:xyz:pupil:xyz", /* etc */ }
So the key columns are null because the map function is emitting doc.id as the key.
See it? doc.id is undefined - emit(doc._id) instead.
Fix the design document map functions (including not emitting doc as value)
{
"_id": "_design/types",
"views": {
"classes": {
"map": "function(doc){ if(doc.type == \"class\"){emit(doc._id);} }"
},
"pupils": {
"map": "function(doc){ if(doc.type == \"pupil\"){emit(doc._id);} }"
}
}
}
Given the two hypothetical documents, the pupils index now looks like this
id
key
value
class:xyz:pupil:abc
class:xyz:pupil:abc
null
class:xyz:pupil:xyz
class:xyz:pupil:abc
null
Now that the view index's key has a value the query will operate as intended.
I highly recommend using Fauxton as it provides a quick means to view an index among other things.

CouchDB Count Reduce with timestamp filtering

Let's say I have documents like so:
{
_id: "a98798978s978dd98d",
type: "signature",
uid: "u12345",
category: "cat_1",
timestamp: UNIX_TIMESTAMP
}
My goal is to be able to count all signature's created by a certain uid but being able to filter by timestamp
Thanks to Alexis, I've gotten to this far with a reduce _count function:
function (doc) {
if (doc.type === "signature") {
emit([doc.uid, doc.timestamp], 1);
}
}
With the following queries:
start_key=[null,lowerTimestamp]
end_key=[{},higherTimestamp]
reduce=true
group_level=1
Response:
{
"rows": [
{
"key": [ "u11111" ],
"value": 3
},
{
"key": [ "u12345" ],
"value": 26
}
]
}
It counts the uid correctly but the filter doesn't work properly. At first I thought it might be a CouchDB 2.2 bug, but I tried on Cloudant and I got the same response.
Does anyone have any ideas on how I could get this to work with being ale to filter timestamps?
When using compound keys in MapReduce (i.e. the key is an array of things), you cannot query a range of keys with a "leading" array element missing. i.e. you can query a range of uuids and get the results ordered by timestamp, but your use-case is the other way round - you want to query uuids by time.
I'd be tempted to put time first in the array, but unix timestamps are not so good for grouping ;). I don't known the ins and outs of your application but if you were to index a date instead of a timestamp like so:
function (doc) {
if (doc.type === "signature") {
var date = new Date(doc.timestamp)
var datestr = date.toISOString().split('T')[0]
emit([datestr, doc.uuid], 1);
}
}
This would allow you to query a range of dates (to the resolution of a whole day):
?startkey=["2018-01-01"]&endkey=["2018-02-01"]&group_level=2
albeit with your uuids grouped by day.

Finding Overlap date ranges between startdate and enddate in couch Db or cloudant

Hello I am building a reservation app using database as couchDb. I have several reservation documents and each of them has roomId, start date and end date.
Now when user creates a meeting request with roomId, start date and end date, I need to search for overlaps time ranges between the start time and endtime in the existing reservations and create a reservations only when there is no conflict. Along with this I also need to check for roomid.
The requirement is similar to Determine Whether Two Date Ranges Overlap.
I had created a view on my couch db emitting three keys:
function (doc) {
if (doc.type == "reservation") {
emit([doc.roomid, doc.startTime, doc.endTime], doc);
}
}
I did try creating something like
?startkey=["1970-01-01T00:00:00Z", ""]&endkey=["\ufff0", "1971-01-01T00:00:00Z"]
However I am not really getting how to compound query the view to find range of date along with the roomid.
Any help would be appreciated.
You could use Cloudant Query and specify the (StartA <= EndB) and (EndA >= StartB) search condition that's outlined in the referenced answer.
Create an index
Send a POST request to the _index endpoint, passing the following JSON data structure as payload.
POST https://$USERNAME:$PASSWORD#$HOST/$DATABASE/_index HTTP/1.1
{
"index": {
"fields": [
{ "name":"startTime",
"type":"string"
},
{
"name":"endTime",
"type":"string"
},
{
"name":"roomid",
"type":"string"
}
]
},
"type": "text"
}
Query the index
Send a POST request to the _find endpoint, passing the following JSON data structure as payload.
POST https://$USERNAME:$PASSWORD#$HOST/$DATABASE/_find HTTP/1.1
{
"selector": {
"startTime": {
"$lte": "2017-03-06T15:00:00Z"
},
"endTime": {
"$gte": "2017-03-06T14:00:00Z"
},
"roomid": {
"$eq": "room 123"
}
}
}
Replace the timestamp and room identifier values as needed. If the query returns at least one document you've encountered a booking conflict.

Mongoose get array of Date with Values

i wanna enter a startDate and a endDate to my Mongoose Aggregation to get the registered Users foreach day between the range. I know i could user the normal count function but i thinkt its better to use the aggregations for it what do you think?
var startDate = 2016-01-05;
var endDate = 2016-01-07;
history : [
['2016-01-05', 23], // Day 1 = 23 Users
['2016-01-06', 34], // Day 2 = 34 Users
['2016-01-07', 43] // Day 3 = 43 Users
];
so i'm searching for something like
User.aggregate(
[
{
"$group": {
"created": {
$gte: startDate,
$lt: endDate
}
}
}
], function (err, users) {
history.push(users);
}
);
Aggregation indeed would be the ideal solution but how it generates the result is different from your expected output, depending on your application needs (I presume most probably you want to use this data
to display in a graph).
You could approach this in a couple of ways. Not the best solution since it depends on how your data is structured, i.e. it assumes the created date field in your users collection follows a time series (a users is created per day) and is a proper mongo date, but will at least get you going.
Let's consider the aggregation pipeline first. Since you want to produce a list of user counts for each day within a specified data range, you could construct
your pipeline in such a way that after the $match pipeline step, use the $group operator to create as the group key a string representation of the created date field using the $dateToString operator, which can be used to group by a day in the "YYYY-MM-DD" format. Then get the count of each accumulated documents using the $sum
operator:
var startDate = new Date("2016-01-05");
var endDate = new Date("2016-01-08");
var pipeline = [
{
"$match": {
"created": {
"$gte": startDate,
"$lt": endDate
}
}
},
{
"$group": {
"_id": {
"yearMonthDay": {
"$dateToString": {
"format": "%Y-%m-%d",
"date": "$created"
}
}
},
"count": { "$sum": 1 }
}
}
];
You can then run the aggregation pipeline, manipulate the result to get the final array in the desired format:
User.aggregate(pipeline, function (err, users){
if (err) {/* handle error */ }
console.log(JSON.stringify(users, null, 4));
var data = users.map(function (u){ return [u._id.yearMonthDay, u.count]; });
console.log(JSON.stringify(data, null, 4));
});

Map composite key sort

I try to display app's log entries from couchdb - each log entry contains timestamp, log tag and client's remote IP, my map function is :
{
"_id": "_design/log",
"language": "javascript",
"views": {
"browse": {
"map": "function(doc){ if (doc.type=='log') {emit([doc.date,doc.tag,doc.ip], doc);}}"
}
}
}
Now how can I get log entries for specified IP(tag) sorted by date ?
Already tried variants of : /_design/log/_view/browse?startkey=["info","8.8.8.8"] with no success.
Your start key needs 3 elements: date, tag, and ip.
Your unsuccessful query only has 2 elements in the start key.
There is some documentation out there for composite keys. In the example used, they have a different key for year, month, and day. You can find the example in this book: http://shop.oreilly.com/product/0636920018247.do
Map function:
function(doc) {
if (doc.type === 'log') {
emit([doc.tag, doc.ip, doc.date], 1);
}
}
Query parameters (properly url-encoded):
?startkey=["info","8.8.8.8"]&endkey=["info","8.8.8.8",{}]&include_docs=true
The results are sorted by date because tag and ip are fixed.

Resources