PouchDB Grouping and Summarizing - javascript

I am using pouchdb and have a document structure like this:
{
"_id": "1",
"title": "Title",
"categories": {
"category1": {
"salesx": [
{
"date": "2016-09-15 00:00:00",
"qty": "2"
},
{
"date": "2016-09-16 00:00:00",
"qty": "3"
}
],
"salesy": [
[
{
"date": "2016-09-15 00:00:00",
"qty": "1"
}
]
]
}
},
"_rev": "rev"
}
I now want to get something like this as a result from pouchdb:
{
"_id": "1",
"title": "Title",
"categories": {
"category1": {
"salesx": 2 + 3 = 5,
"salesy": [
[
{
"date": "2016-09-15 00:00:00",
"qty": "1"
}
]
]
}
},
"_rev": "rev"
}
So, salesx should be grouped and the qty should be summarized.
salesy should not be changed.
I also want to add a where clause to the date field.
I tried to start with a map function which selects the correct dates. But I don't know what to emit to group the qty later.
function myMapFunction(doc) {
doc.categories.forEach(category => {
category.salesx.forEach(salex => {
if (salex.date >= mydate) {
emit(?)
}
})
})
}
I can't find a good example on pouchdb docs. They only provide examples for grouping multiple documents together.
Does anyone know how I can achieve grouping the document?

I modified the documents like below, to convert the qty field from string values to number values, to be able to do math operations:
{
"_id": "sale0000",
"_rev": "2-5cd6fff48f9fd099481d3b523ff1191f",
"title": "Title",
"categories": {
"category1": {
"salesx": [
{
"date": "2016-09-15 00:00:00",
"qty": 2
},
{
"date": "2016-09-16 00:00:00",
"qty": 3
}
],
"salesy": [
[
{
"date": "2012-09-15 00:00:00",
"qty": 1
}
]
]
}
}
}
As you mentioned in the comments:
All documents look exactly like the one I already showed. Except the
number of entries in salesx and the number of categories (e.g.
category1, category2 ...) is modified
Based on your above statement, I created in my sample database some documents with varying number of entries in salesx and varying number of categoiry1, category2, etc., but each salesy has only one entry.
Here is another one of my sample documents:
{
"_id": "sale0002",
"_rev": "3-12bf5c872fc124c1f0a5a4a108cb4f7a",
"title": "Title",
"categories": {
"category1": {
"salesx": [
{
"date": "2016-09-15 00:00:00",
"qty": 2
},
{
"date": "2016-09-16 00:00:00",
"qty": 3
},
{
"date": "2017-10-16 00:00:00",
"qty": 9
}
],
"salesy": [
[
{
"date": "2014-09-15 00:00:00",
"qty": 1
}
]
]
},
"category2": {
"salesx": [
{
"date": "2018-01-15 00:00:00",
"qty": 2
},
{
"date": "2012-08-16 00:00:00",
"qty": 3
},
{
"date": "2015-10-16 00:00:00",
"qty": 7
}
],
"salesy": [
[
{
"date": "2011-03-15 00:00:00",
"qty": 1
}
]
]
}
}
}
I'm not sure if I understand what exactly you intend, but I developed the following view map function:
function (doc) {
if(doc.categories){
for(var categ in doc.categories){
var salesx_qty_sum=0;
for(var i=0, len=doc.categories[categ].salesx.length; i<len; i++){
salesx_qty_sum += doc.categories[categ].salesx[i].qty
}
emit(
doc.categories[categ].salesy[0][0]['date'], //emit the date of salesy as the key
//my understanding is that you need to index/sort
//according to date of salesy
[
salesx_qty_sum, //emit the sum of qty for salesx as value
doc.categories[categ].salesy[0][0]['qty'] //emit qty for salesy (unchanged) as value
]
);
}
}
}
In my sample database I created four documents like yours with different number of entries in salesx and also varying number of categories. There is only one entry inside each salesy:
$ curl -k -X GET 'https://admin:****#192.168.1.106:6984/sample/_all_docs'
{"total_rows":53,"offset":0,"rows":[
...
...
{"id":"_design/by_date","key":"_design/by_date","value":{"rev":"20-04cb881624aa819dac13f69c688f2124"}},
...
...
{"id":"sale0000","key":"sale0000","value":{"rev":"2-5cd6fff48f9fd099481d3b523ff1191f"}},
{"id":"sale0001","key":"sale0001","value":{"rev":"2-e8ee019fb0ad076b82d3f4772f736559"}},
{"id":"sale0002","key":"sale0002","value":{"rev":"3-12bf5c872fc124c1f0a5a4a108cb4f7a"}},
{"id":"sale0003","key":"sale0003","value":{"rev":"2-6d40368ddd16b9d02b908ea95d061c7e"}}
]}
The above view map (named by_date) is indexing my documents like below, in which the key is the date of salesy. Based your description, I assume there should be only one entry in each salesy in each category. Also, the value below is an array in which first element is sum of qty for salesx, and the second element is unchanged qty of salesy:
$ curl -k -X GET 'https://admin:admin#192.168.1.106:6984/sample/_design/by_date/_view/by_date'
{"total_rows":6,"offset":0,"rows":[
{"id":"sale0002","key":"2011-03-15 00:00:00","value":[12,1]},
{"id":"sale0000","key":"2012-09-15 00:00:00","value":[5,1]},
{"id":"sale0001","key":"2013-05-20 00:00:00","value":[12,1]},
{"id":"sale0002","key":"2014-09-15 00:00:00","value":[14,1]},
{"id":"sale0003","key":"2015-04-15 00:00:00","value":[5,1]},
{"id":"sale0003","key":"2018-04-05 00:00:00","value":[5,1]}
]}
You can query the by_date view with startkey and endkey to get the results between two dates, like this:
$ curl -k -X GET 'https://admin:admin#192.168.1.106:6984/sample/_design/by_date/_view/by_date?startkey="2013"&endkey="2015"'
{"total_rows":6,"offset":2,"rows":[
{"id":"sale0001","key":"2013-05-20 00:00:00","value":[12,1]},
{"id":"sale0002","key":"2014-09-15 00:00:00","value":[14,1]}
]}

Related

How can i filter result if i have array in body

i have a payload
{
"category": "Mobile",
"price": {
"from": "10",
"to": "50"
},
"location": [
"Jakrta",
"Bandung",
"Surabaya"
],
"rating": [
"1",
"2",
"3"
]
}
i want to find all object which have rating 1 or 2 or 3 and also have any location
Basically i am creating a filter for an ecommerce store i which we will get multiple location and multiple ratings as well so we will return only those object which have matched property. i am attaching a screenshot of UI for better understanding.
i want to run this filter with multiple location and multiple checked checkbox
You can do create a filter dynamically:
const { category, price, location, rating } = req.body;
const filter = {};
if (category) filter.category = category;
if (price) filter.price = { $gte: parseInt(price.from, 10), $lte: parseInt(price.to, 10) };
if (location?.length) filter.location = { $in: location };
if (rating?.length) filter.rating = { $in: rating };
const data = await Collection.find(filter);
If you want to filter your objects, you should use filter() from your array :
const arr = [{
"category": "Mobile1",
"price": {
"from": "10",
"to": "50"
},
"location": [
"Jakrta",
"Bandung",
"Surabaya"
],
"rating": [
"1",
"2",
"3"
]
},
{
"category": "Mobile2",
"price": {
"from": "10",
"to": "50"
},
"location": [
"Jakrta",
"Bandung",
"Surabaya"
],
"rating": [
"2",
"3"
]
}];
const result = arr.filter(el => el.rating.includes("1") || el.rating.includes("2") || el.rating.includes("3"));
console.log(result);

How can I .filter an object by elements within an array inside an object?

I've been playing around trying to learn in an API project using Postman and conducting tests using JavaScript. So far, I have succeeded with the help of reading on websites and watching YouTube videos. Of course, previous tests and playing around have been fairly easy but now I came to a stop. I really tried to figure this out for several weeks but I need further guidance, a push in the right direction or direct help.
What I'm trying to do is to filter out some of the response to only view objects that contain specific data.
To do that, I'm using a filter where I want all products containing a specific value inside an array "product_option_values".
My first approach was to see if I could sort products having any values from the first array, and it worked. It filters just fine.
var filterSmall = jsonData.products.filter(fs => fs.associations.product_option_values);
My next approach was to get to my goal of filtering out products according to specific values inside this array. I tried many simple .(dot) combinations and pointing to [index] to access it without any luck. (I must add that I know how to access this from a specific product, but that way doesn't work when filtering).
I've also tried other approaches such as:
var filterSmall = jsonData.products.filter(fs => fs.associations["product_option_values", 0, "name"] === "S");
and other similar combinations.
This is a very shortened sample of the structure of "products" which in its full form consists of 20 products and far more values inside of it:
{
"products": [
{
"id": 16,
"manufacturer_name": "Graphic Corner",
"quantity": "0",
"price": "12.900000",
"indexed": "1",
"name": "Mountain fox notebook",
"associations": {
"categories": [
{
"id": "2"
},
{
"id": "6"
}
],
"product_option_values": [
{
"id": "22"
},
{
"id": "23"
}
]
}
},
{
"id": 17,
"manufacturer_name": "Graphic Corner",
"quantity": "0",
"price": "12.900000",
"indexed": "1",
"name": "Brown bear notebook",
"associations": {
"categories": [
{
"id": "2"
},
{
"id": "6"
}
],
"product_option_values": [
{
"id": "23"
},
{
"id": "24"
}
]
}
}
]
}
and here is a small and expanded sample from product_option_values:
{
"product_option_values": [
{
"id": 1,
"id_attribute_group": "1",
"color": "",
"position": "0",
"name": "S"
},
{
"id": 2,
"id_attribute_group": "1",
"color": "",
"position": "1",
"name": "M"
},
{
"id": 3,
"id_attribute_group": "1",
"color": "",
"position": "2",
"name": "L"
}
]
}
How do I proceed? Did I do anything correct or even close to it?
Perhaps I've been staring at this for too long.
Thanks in advance.
If you want to compare nested attributes you have to transform the objects (e.g. by using a map operation), so that the relevant attributes are easily accessible for a comparison. If you want to filter by product_option_value id, you could do something like this:
const jsonData = {
"products": [
{
"id": 16,
"manufacturer_name": "Graphic Corner",
"quantity": "0",
"price": "12.900000",
"indexed": "1",
"name": "Mountain fox notebook",
"associations": {
"categories": [
{
"id": "2"
},
{
"id": "6"
}
],
"product_option_values": [
{
"id": "22"
},
{
"id": "23"
}
]
}
},
{
"id": 17,
"manufacturer_name": "Graphic Corner",
"quantity": "0",
"price": "12.900000",
"indexed": "1",
"name": "Brown bear notebook",
"associations": {
"categories": [
{
"id": "2"
},
{
"id": "6"
}
],
"product_option_values": [
{
"id": "23"
},
{
"id": "24"
}
]
}
}
]
};
const sample = {
"product_option_values": [
{
"id": 22,
"id_attribute_group": "1",
"color": "",
"position": "0",
"name": "S"
},
{
"id": 2,
"id_attribute_group": "1",
"color": "",
"position": "1",
"name": "M"
},
{
"id": 3,
"id_attribute_group": "1",
"color": "",
"position": "2",
"name": "L"
}
]
};
const ids = sample.product_option_values.map((el) => String(el.id));
console.log(ids);
const filtered = jsonData.products.filter((fs) => fs.associations.product_option_values.map((e) => e.id).some((f) => ids.includes(f)));
console.log(filtered);

How to combine two JSON objects into an array

I have two JSON files - one pertaining to English Premier League data of 2015-16 and other of 2016-17. The JSON data in each file is as follows (extract only):
{
"name": "English Premier League 2015/16",
"rounds": [
{
"name": "Matchday 1",
"matches": [
{
"date": "2015-08-08",
"team1": {
"key": "manutd",
"name": "Manchester United",
"code": "MUN"
},
"team2": {
"key": "tottenham",
"name": "Tottenham Hotspur",
"code": "TOT"
},
"score1": 1,
"score2": 0
},
and so on... lot of name, matches like this in the rounds array.
The data of 2016-17 is similar to above:
{
"name": "English Premier League 2016/17",
"rounds": [
{
"name": "Matchday 1",
"matches": [
{
"date": "2016-08-13",
"team1": {
"key": "hull",
"name": "Hull City",
"code": "HUL"
},
"team2": {
"key": "leicester",
"name": "Leicester City",
"code": "LEI"
},
"score1": 2,
"score2": 1
},
and so on... lot of name, matches like this in the rounds array.
These two are in two separate json files. I am developing an application in Angular 2 and have used a data service to get this data. That part was successful. However I need to use ngFor for creating rows in table and for that I require this data to be iterable like an array.
I have tried to convert these two json objects into an array but could not succeed.
1 I have initialised an empty array and tried to do array.push for each object. That did not work
arr=[];
if(this.data1516!=null && this.data1516!=undefined) {arr.push(this.data1516);}
if(this.data1617!=null && this.data1617!=undefined) {arr.push(this.data1617);}
2 I tried Object. assign -
this.obj=Object.assign({},this.data1516,this.data1617);
and then tried converting the object into array, even that did not work
All I want the final json single file to be an array of those two objects, like this:
[ {obj1} , {obj2} ]
There was a extra ] inside arr.push
This should work :
arr=[];
if(this.data1516!=null && this.data1516!=undefined) {
arr.push(this.data1516);
}
if(this.data1617!=null && this.data1617!=undefined) {
arr.push(this.data1617);
}
OR Shorter version (ES6)
arr = [ ...this.data1516 , ...this.data1617 ];

Create collections through iterating a JSON file

I'm trying to make an event-based calendar by iterating through an array of json objects with individual dates using javascript.
What I want to achieve is a new structure from these objects, where i get the year from the object and make that a unique key which can contain multiple months as keys retrieved from the objects, which then again can contain multiple days as keys retrieved from the objects, which again contains multiple objects... phew..
F.ex., say I have this json file:
"objects": [
{
"dateTime": {
"date": "2016-12-24"
},
"values": {
"value1": "some value",
"value2": 700
}
}, {
"dateTime": {
"date": "2016-12-24"
},
"values": {
"value1": "other value",
"value2": 3100
}
}, {
"dateTime": {
"date": "2016-12-25"
},
"values": {
"value1": "random value",
"value2": 300
}
}, {
"dateTime": {
"date": "2017-01-02"
},
"values": {
"value1": "value",
"value2": 100
}
}]
Now I want to iterate through each object and make something like this:
[{
"2017": [{
"january": [{
"monday": [
object
]
}]
},
"2016": {
"december": [{
"saturday": [
object,
object
],
"sunday": [
object
]
}]
}]
}]
So I don't want any duplicates of any object which is set as key. What path should I go for? I've been looking into Map, WeakMap, Set and WeakSet, but I just can't figure out how to do this properly.

Can't get json data inside array

[
{
"May": [
{
"year": 1994,
"date": "2"
},
{
"Sequence": 2,
"Type": "Images"
}
],
"_id": "1122"
}
]
I can get id except "date" which is inside array. And date just show me undefined.
var data = [
{
"May": [
{
"year": 1994,
"date": "2"
},
{
"Sequence": 2,
"Type": "Images"
}
],
"_id": "1122"
}
];
alert(data[0].May[0]["date"]);
You should use arr[i].May[0]['date'], date is inside the object of the 0th index of array May.
Array will be start with the index 0 only . so from your json data 0th position only have the key named "date". So you should use like #void answer.
If you had doubt about whether data is have or not use like below
if(data[0].May[0]["date"])
alert(data[0].May[0]["date"]);
Thank you :)

Categories

Resources