Matching for the Values in an array in javascript - javascript

I have bunch of objects in an array with format as below:
[
{
"card_details": {
"cardType": "gift"
},
"merchant_details": {
"merchantName": "Walter Heisenberg1",
"timeZone": "+05:30",
}
},
{
"card_details": {
"cardType": "coupon",
"cardTitle": "Coupon",
"messageUser": "Hi",
"punchCount": null,
"messageReachPunchLimit": "Get your Freebie!",
"merchantId": "59c214000e1a7825184cb813",
"expiryDate": "21 Sep 2019",
"discountPercent": "15",
"cardImageUrl": ""
},
"merchant_details": {
"merchantName": "Walter Heisenberg1",
"timeZone": "+05:30"
}
},
{
"card_details": {
"cardType": "punch",
"cardTitle": "BlueM2",
"messageUser": "Welcome!",
"expiryDate": "21 Sep 2019",
"punchCount": 25,
"messageReachPunchLimit": "Get your Freebie!",
"merchantId": "59c214000e1a7825184cb813",
"cardImageUrl": "http://139.59.179.111/cloopapi/undefined"
},
"merchant_details": {
"merchantName": "Walter Heisenberg1",
"timeZone": "+05:30"
}
}
]
I want to filter the objects based on cardType in the card_details object. But I want to search from the array. For example, if I search for ["coupon","gift"], then I should get the all the cards which have the card_details.cardType as coupon or gift.
I need to be able to do this in Node.js,i.e., Javascript.

You can use ES6 filter and includes functions here:
collection.filter(item => ['coupon', 'gift'].includes(item.card_details.cardType))

Related

MongoDB Aggregation - Field must be a accumulator object in group stage

I am new to mongodb aggregation. Let's say I have this data:
[
{
"end_year": 2020,
"intensity": 12,
"sector": "Information Technology",
"topic": "robot",
"insight": "62 market research reports study robotics industry",
"url": "http://robohub.org/62-market-research-reports-study-robotics-industry/",
"region": "",
"start_year": 2016,
"impact": "",
"added": "July, 16 2016 02:44:49",
"published": "July, 11 2016 00:00:00",
"country": "",
"relevance": 3,
"pestle": "Economic",
"source": "Robothub",
"title": "Forecasts the industrial robotics market in APAC to grow at a CAGR of 8.7% during the period 2016-2020 in the top 5 segments.",
"likelihood": 4
},
{
"end_year": "",
"intensity": 2,
"sector": "Government",
"topic": "government",
"insight": "Oil, Greed, and Grievances in the Middle East and North Africa",
"url": "https://www.newsecuritybeat.org/2016/07/oil-greed-grievances-middle-east-north-africa/",
"region": "",
"start_year": "",
"impact": "",
"added": "July, 16 2016 01:12:21",
"published": "July, 12 2016 00:00:00",
"country": "",
"relevance": 1,
"pestle": "Political",
"source": "New Security Beat",
"title": "Countries threatened by larger-scale insurgencies might want to consider giving regional groups some share in central government decision-making.",
"likelihood": 2
}
]
This is my query:
// return all the countries associated with a single topic
const data = await Data.aggregate([
{ $match: {} },
{ $group: { _id: "$topic",country: ["$country"],likelihood: ["$likelihood"],relevance: ["$relevance"],intensity: ["$intensity"] } }
])
I want to return all countries,likelihoods,relevances associated with a single/common topic
I know how to get the first and last ones using $first and $last operators. How do I get all of them in an array?
We can use $push operator to add all of the field values:
const data = await Data.aggregate([
{ $match: {} },
{ $group: { _id: "$topic",data: { $push: { country: "$country",likelihood: "$likelihood",relevance: "$relevance",intensity: "$intensity" } } } }
])

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);

Trying to merge nested properties of objects inside array into single object containing all nested properties using reduce, only getting single value

I have an array of objects each with a groupName key/value and then an item key with an array of objects as it's value.
I'm trying to use .reduce() with a forEach to iterate over the main array and merge all of the item values into a new Object with a single groupName and an items array containing all the original item values.
Every time I run the function I only get back the first value and I'm trying to figure out what I'm doing wrong.
Current Function:
const testMerge = moviesArray.reduce((acc, curr) => {
const { items } = curr;
items.forEach((el) => (acc[el] = el));
return acc;
}, {});
console.log('Test merge: ', testMergeObjects);
// returns [object Object]: groupName: The Town, year: 2010
moviesArray:
[
{
"groupName": "comedy",
"items": [
{
"name": "I Love You, Man",
"year": "2009"
}
]
},
{
"groupName": "sci fi",
"items": [
{
"name": "The Matrix",
"year": "1999"
},
{
"name": "Looper",
"year": "2012"
}
]
},
{
"groupName": "crime thriller",
"items": [
{
"name": "The Town",
"year": "2010"
}
]
}
]
Desired Result:
[
"groupName": "movies",
"items": [
{
"name": "I Love You, Man",
"year": "2009"
},
{
"name": "The Matrix",
"year": "1999"
},
{
"name": "Looper",
"year": "2012"
},
{
"name": "The Town",
"year": "2010"
}
]
]
You can use array#map and array#concat to merge items in movie array.
const data = [ { "groupName": "comedy", "items": [ { "name": "I Love You, Man", "year": "2009" } ] }, { "groupName": "sci fi", "items": [ { "name": "The Matrix", "year": "1999" }, { "name": "Looper", "year": "2012" } ] }, { "groupName": "crime thriller", "items": [ { "name": "The Town", "year": "2010" } ] } ],
items = [].concat(...data.map(({items}) => items)),
output = { groupName: "movies", items}
console.log(output);
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to enhance a json object?

I am recieving a json object from an api as following:
[
{"id":998,
"client":{"id":"AF01072","name":"Vivek","lastName":"Joshi","phone":123},
"membership":{"type":"Semi-Annually","price":18000},
"start_date":"2019-11-19","end_date":"2020-05-16","payment":12000,"balance":0
},
{"id":1004,
"client":{"id":"AF01072","name":"Vivek","lastName":"Joshi","phone":123},
"membership":{"type":"Annually","price":30000},
"start_date":"2020-08-27","end_date":"2021-08-27","payment":30000,"balance":5000,
}
]
in angular when I loop to print the data 'client' information prints two times, because it is repeated two times.
<div *ngFor="let c of clientinfo">
{{c.client.name}}
{{c.membership.type}}
{{c.membership.price}}
{{c.start_date}}
{{c.end_date}}
.
.
.
</div>
How can I enhance this data so I get only client information once but the rest stay as they are?
thanks in advance
Whenever you need to group some data by some value you can use an object because object properties are guaranteed to never be duplicated. You have to be careful however because properties can be overwritten.
First, let's settle on a structure that works. The following is one such structure that can work:
{
[client.id] : {
client: client,
info : [
{ membership, start_date },
{ membership, start_date },
..
]
},
[client.id] : {
client: client,
info : [
{ membership, start_date },
{ membership, start_date },
..
]
},
..
}
There are other ways to arrange the data but the key is to exploit objects to implement a map/hash/associative array of key/value pairs. With this we can group the data from your array:
let group = {};
jsonData.forEach(x => {
// check if group already contain this client:
if (!group[x.client.id]) {
// auto-create array if does not exist
group[x.client.id] = {
client: x.client,
info: []
};
}
group[x.client.id].info.push({
membership: x.membership,
start_date: x.start_date
});
});
Now you have an object grouped by client id where each property is an object that has an info array that contains membership information.
If you need to loop over this data structure you can convert it back to an array by doing:
let groupArray = Object.values(group);
This will give you the following data structure:
[
{
client: client,
info : [
{ membership, start_date },
{ membership, start_date },
..
]
},
{
client: client,
info : [
{ membership, start_date },
{ membership, start_date },
..
]
},
..
]
An array of client objects with an info property containing an array of membership data. For your sample data it would be something like:
[
{
"client":{"id":"AF01072","name":"Vivek","lastName":"Joshi","phone":123},
"info": [
{
"membership":{"type":"Semi-Annually","price":18000},
"start_date":"2019-11-19",
"end_date":"2020-05-16",
"payment":12000,"balance":0
},
{
"membership":{"type":"Annually","price":30000},
"start_date":"2020-08-27",
"end_date":"2021-08-27",
"payment":30000,"balance":5000,
}
]
}
]
You need to create array of memberships for each client like below. And in the template file, you need to use two *ngFor loops. One to loop client details and another one to loop the respective client's membership details.
Working stackblitz
const result = [{
"id": 998,
"client": {
"id": "AF01072",
"name": "Vivek",
"lastName": "Joshi",
"phone": 123
},
"membership": {
"type": "Semi-Annually",
"price": 18000
},
"start_date": "2019-11-19",
"end_date": "2020-05-16",
"payment": 12000,
"balance": 0
},
{
"id": 1004,
"client": {
"id": "AF01072",
"name": "Vivek",
"lastName": "Joshi",
"phone": 123
},
"membership": {
"type": "Annually",
"price": 30000
},
"start_date": "2020-08-27",
"end_date": "2021-08-27",
"payment": 30000,
"balance": 5000,
},
{
"id": 1005,
"client": {
"id": "AF01073",
"name": "Some Other",
"lastName": "Joshi",
"phone": 123
},
"membership": {
"type": "Annually",
"price": 30000
},
"start_date": "2020-08-27",
"end_date": "2021-08-27",
"payment": 30000,
"balance": 5000,
}
].reduce((acc, item, i) => {
if (i == 0) {
acc.push(constructCorrectObject(item));
return acc;
}
let foundItem = acc.find(it => it.id === item.client.id);
if (foundItem) {
addMemeberShipDetails(foundItem, item);
return acc;
} else {
acc.push(constructCorrectObject(item));
return acc;
}
}, []);
function constructCorrectObject(item) {
return {
"id": item.client.id,
"name": item.client.name,
"lastName": item.client.lastName,
"phone": item.client.phone,
"membership": [{
"id": item.id,
"type": item.membership.type,
"price": item.membership.price,
"start_date": item.start_date,
"end_date": item.end_date,
"payment": item.payment,
"balance": item.balance,
}]
}
}
function addMemeberShipDetails(acc, item) {
acc.membership.push({
"id": item.id,
"type": item.membership.type,
"price": item.membership.price,
"start_date": item.start_date,
"end_date": item.end_date,
"payment": item.payment,
"balance": item.balance,
});
}
console.log(result);

RethinkDB indexing two fields with time

I have RethinkDB with data/table let say "news" with huge number of data row :
[
{
"author": "author1",
"category_id": "business",
"country": "id",
"created_at": "Wed Aug 15 2018 09:26:52 GMT+07:00",
"description": "description",
"id": "74c25662-7f94-47ef-8a7e-5091924819a9"
},
{
"author": "author2",
"category_id": "business",
"country": "id",
"created_at": "Wed Aug 15 2018 09:26:52 GMT+07:00",
"description": "description2",
"id": "74c25662-7f94-47ef-8a7e-5091924819a9"
},
{
"author": "author3",
"category_id": "sport",
"country": "id",
"created_at": "Wed Aug 15 2018 09:26:52 GMT+07:00",
"description": "description3",
"id": "74c25662-7f94-47ef-8a7e-5091924819a9"
},
{
"author": "author3",
"category_id": "business",
"country": "id",
"created_at": "Wed Aug 15 2018 09:26:52 GMT+07:00",
"description": "description4",
"id": "74c25662-7f94-47ef-8a7e-5091924819a9"
}
.....
]
I need to create index for category_id and created_at (timestamp) and query for certain category and filter by day now (certain date) only. I want to optimize and speed up for query result
I can do it in javascript by filter like this for category_id business and day 15 :
r.table("news").filter({category_id: 'business'}).filter(
r.row("created_at").day().eq(15)
)
But how I can create index for category_id and created_at and query it by certain day of created_at.
r.table("news").indexCreate( ???
thanks
Should be something like this:
r.table('news').indexCreate('businessAndDate', function (doc) {
return doc('category_id').add(doc('created_at').day().coerceTo('string'));
});
Then you can:
r.table('news').getAll('business15', {index: 'businessAndDate'})
You may want to insert a separator between the data (like 'business-15'), and use more than just the day (otherwise, why bother having a full timestamp?), that's up to you and how many .add you're willing to write. ;)
According to the reference, this is called an arbitrary index.

Categories

Resources