Good day, I've spent 2 - 3 hours just to get this working,
so I have this controller.js code:
const b_name = req.params.b;
const m_name = req.params.m;
const result = await cinemaDB.getcinemasbranchesmovies(model, {'details.branches_name': b_name, 'details.movies_name': m_name});
and this db.js code:
/** Get branches's movies by _id */
module.exports.getcinemasbranchesmovies =
async(model, query) => {
return new Promise((resolve, reject) => {
// console.log("branches: " + b_name + "movies: "+ m_name);
if (!query) {
query = {};
}
console.log("branches: ", query);
model.find(query)
.then(res => {
console.log("branches: ", res);
resolve(res);
})
.catch(err => {
reject(err);
console.log(err);
throw err;
});
});
}
and this route.js code:
server.get("/api/cinemas/getcbm/:b/:m",controller.getcinemasbranchesmovies);
EDIT! If you put it in a query:
model.find({'details.branches_name': "Evia", 'details.movies_name': "Greatest"})
now this is the JSON result:
{
"success": true,
"status": "OK",
"data": [
{
"_id": "5ab49348c356c713a836cc15",
"cinemas_name": "Cinemas 3",
"__v": 0,
"details": [
{
"price": 350,
"movies_name": "Black Panther",
"branches_name": "Bataan",
"_id": "5ab49348c356c713a836cc16",
"time": [
"1",
"2",
"3"
]
},
{
"branches_name": "Bataan",
"movies_name": "Black Panther",
"price": 350,
"_id": "5ab494b2c0a83c28e874ace9",
"time": [
"1",
"2",
"3"
]
},
{
"branches_name": "Bataan",
"movies_name": "Black Panther",
"price": 350,
"_id": "5ab495a9d0bebb3d4c26c086",
"time": [
"1",
"2",
"3"
]
},
{
"branches_name": "Bataan",
"movies_name": "December Avenue",
"price": 350,
"_id": "5ab495c5d0bebb3d4c26c087",
"time": [
"1",
"2",
"3"
]
},
{
"branches_name": "Taguig",
"movies_name": "December Avenue",
"price": 350,
"_id": "5ab49d4b2b0ce727dc9a2a07",
"time": [
"1",
"2",
"3"
]
},
{
"branches_name": "Evia",
"movies_name": "December Avenue",
"price": 350,
"_id": "5ab49d522b0ce727dc9a2a08",
"time": [
"1",
"2",
"3"
]
},
{
"branches_name": "Evia",
"movies_name": "Greatest",
"price": 350,
"_id": "5ab4a0e397ca122e8005c19f",
"time": [
"1",
"2",
"3"
]
}
]
}
]
}
Now what I need only is this value to be displayed:
{
"success": true,
"status": "OK",
"data": [
{
"_id": "5ab49348c356c713a836cc15",
"cinemas_name": "Cinemas 3",
"__v": 0,
"details": [
{
"branches_name": "Evia",
"movies_name": "Greatest",
"price": 350,
"_id": "5ab4a0e397ca122e8005c19f",
"time": [
"1",
"2",
"3"
]
}
]
}
]
}
So all in all, I want only to display the specific data I've inputted inside the query of find.
I do search it on google first, but I can't comprehend the way they code it.
So yeah, expanding my comprehension on google, I get it done by using the aggregate function.
replacing model.find -> model.aggregate
it's query is something like:
model.aggregate({$unwind:"$details"},
{
$match:{
"details.branches_name": query1,
"details.movies_name": query2
}
}
)
I hope someone helps by this :D
Related
I'm newbie and sequelize aggregate function makes me confused because it gave me different result than expected. I'm trying to get a total price with sequelize.fn('sum', ...), and somehow sequelize only gives me the the total of first data of the associated model instead of summing all the result. My code as follows:
Training.findAll({
where: {
owner_id: payload
},
attributes: ['id', [sequelize.fn('sum', sequelize.col('training_classes.price')), 'totalPrice']],
include: [{
model: TrainingClass,
as: 'training_classes',
attributes: ['id', 'price'],
}],
group: ['Training.id', 'training_classes.id']
})
And the result of the query :
[
{
"id": "45",
"totalPrice": "300000",
"training_classes": [
{
"id": "94",
"price": "300000"
}
]
},
{
"id": "8",
"totalPrice": "1000000",
"training_classes": [
{
"id": "14",
"price": "1000000"
},
{
"id": "15",
"price": "300000"
},
{
"id": "16",
"price": "200000"
}
]
},
{
"id": "47",
"totalPrice": "100000",
"training_classes": [
{
"id": "97",
"price": "100000"
}
]
},
{
"id": "39",
"totalPrice": "1000000",
"training_classes": [
{
"id": "81",
"price": "1000000"
},
{
"id": "82",
"price": "300000"
}
]
},
{
"id": "24",
"totalPrice": "300000",
"training_classes": [
{
"id": "46",
"price": "300000"
}
]
},
{
"id": "6",
"totalPrice": "200000",
"training_classes": [
{
"id": "11",
"price": "200000"
}
]
},
{
"id": "49",
"totalPrice": "100000",
"training_classes": [
{
"id": "100",
"price": "100000"
},
{
"id": "99",
"price": "1000000"
},
{
"id": "101",
"price": "100000"
}
]
},
{
"id": "20",
"totalPrice": "200000",
"training_classes": [
{
"id": "38",
"price": "200000"
},
{
"id": "35",
"price": "400000"
},
{
"id": "37",
"price": "500000"
},
{
"id": "36",
"price": "100000"
}
]
},
]
as you can see, the totalPrice only from the first element of training_classes, not the entire data of it. How can I resolve this? Thank you in advance
If you want to sum all records in TrainingClass that have the same Training.id then you need to indicate no attributes for TrainingClass and indicate only Training.id in group option:
Training.findAll({
where: {
owner_id: payload
},
attributes: ['id', [sequelize.fn('sum', sequelize.col('training_classes.price')), 'totalPrice']],
include: [{
model: TrainingClass,
as: 'training_classes',
attributes: [],
}],
group: ['Training.id']
})
If you group by TrainingClass.id then you'll get grouped results for each record that has unique TrainingClass.id value and literally every record of TrainingClass has unique id value.
I have a category collection and I want to get category by id with some options. This is collection's structure in database.
[
{
"_id": "5d67296bf35b984e74486924",
"name": "Dinrk",
"images": [],
"recipes": [
{
"name": "Coffee",
"time": 20,
"img": "https://google.com/image-example.jpg",
"des": "This is description",
"serving": 2,
"components": [
{
"name": "Dink 1",
"quantity": "1"
},
{
"name": "Dink 2",
"quantity": "1"
},
{
"name": "Dink 2",
"quantity": "1"
}
],
"cook_steps": [
{
"des": "This is description",
"pictures": []
},
{
"des": "This is description",
"pictures": []
}
]
},
{
"name": "Coffee",
"time": 20,
"img": "https://google.com/image-example.jpg",
"des": "This is description",
"serving": 2,
"components": [
{
"name": "Dink 1",
"quantity": "1"
},
{
"name": "Dink 2",
"quantity": "1"
}
],
"cook_steps": [
{
"des": "This is description",
"pictures": []
},
{
"des": "This is description",
"pictures": []
}
]
}
]
},
{
"_id": "5d67296bf35b984e74486435555",
"name": "Cake",
"images": [],
"recipes": [
{
"name": "Cake",
"time": 20,
"img": "https://google.com/image-example.jpg",
"des": "This is description",
"serving": 2,
"components": [
{
"name": "Cake 1",
"quantity": "1"
},
{
"name": "Cake 2",
"quantity": "1"
},
{
"name": "Cake 2",
"quantity": "1"
}
],
"cook_steps": [
{
"des": "This is description",
"pictures": []
},
{
"des": "This is description",
"pictures": []
}
]
},
{
"name": "Coffee",
"time": 20,
"img": "https://google.com/image-example.jpg",
"des": "This is description",
"serving": 2,
"components": [
{
"name": "Cake 1",
"quantity": "1"
}
],
"cook_steps": [
{
"des": "This is description",
"pictures": []
},
{
"des": "This is description",
"pictures": []
}
]
}
]
}
]
This is my code to try categoryId = "5d67296bf35b984e74486924"
Category.aggregate([
{
$match: {'_id': categoryId}
},
{
$unwind: '$recipes'
},
{
$project: {
'total_components': {'$size': '$recipes.components'},
'total_cook_steps': {'$size': '$recipes.cook_steps'}
}
}
]).then(function(data) {
}, function(err) {
})
And expected result is
{
"_id": "5d67296bf35b984e74486924",
"name": "Dinrk",
"images": [],
"recipes": [
{
"name": "Coffee",
"time": 20,
"img": "https://google.com/image-example.jpg",
"des": "This is description",
"serving": 2,
"total_components": 3,
"total_cook_steps": 2
},
{
"name": "Coffee",
"time": 20,
"img": "https://google.com/image-example.jpg",
"des": "This is description",
"serving": 2,
"total_components": 2,
"total_cook_steps": 2
}
]
}
But when I run above my code, result is [].
If you understand my problem, please help me. I have search a lot, but not found solution. So I want to ask everyone. Thankyou so much.
Your query is not giving you the desired result since Mongoose does not auto-cast the 24 char hex string to ObjectId in its aggregate pipeline since $project and $group can change the schema in surprising ways that it becomes hard to infer what should be an ObjectId.
You need to manually convert the categoryId
string to ObjectId using the mongoose.Types.ObjectId method.
Compute the new fields within a $map operator instead of $unwind as this allows you an aggregate operation with fewer pipeline steps
Category.aggregate([
{ '$match': { '_id': mongoose.Types.ObjectId(categoryId) } },
{ '$addFields': {
'recipes': {
'$map': {
'input': '$recipes',
'in': {
'name': '$$this.name',
'time': '$$this.time',
'img': '$$this.img',
'des': '$$this.des',
'serving': '$$this.serving',
'total_components': { '$size': '$$this.components' },
'total_cook_steps': { '$size': '$$this.cook_steps' }
}
}
}
} }
]).then(function(data) {
}, function(err) {
})
I work with an API that returns a rather particular JSON file ...
It's been 2 days that I try to do something but I can not do it, that's why I leave it to you :)
First of all my JSON file looks like:
[
{
"_id": 14080,
"name": "Amulette Séculaire",
"lvl": "200",
"type": "Amulette",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/200/1230.png",
"url": "https://www.dofus.com/fr/mmorpg/encyclopedie/equipements/14080-amulette-seculaire",
"description": "Finalement, le secteur de la bijouterie n'a pas tellement évolué ces cent dernières années.",
"stats": [
{
"Vitalité": {
"from": "251",
"to": "300"
}
},
{
"Intelligence": {
"from": "61",
"to": "80"
}
},
{
"Agilité": {
"from": "16",
"to": "25"
}
},
{
"Sagesse": {
"from": "31",
"to": "40"
}
},
{
"PA": {
"from": "1"
}
},
{
"Prospection": {
"from": "16",
"to": "20"
}
},
{
"Dommages Feu": {
"from": "8",
"to": "12"
}
},
{
"Dommages Air": {
"from": "8",
"to": "12"
}
},
{
"% Résistance Neutre": {
"from": "6",
"to": "8"
}
},
{
"% Résistance Feu": {
"from": "6",
"to": "8"
}
},
{
"Résistance Critiques": {
"from": "11",
"to": "15"
}
}
],
"condition": [],
"recipe": [
{
"Galet brasillant": {
"id": "12740",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/12740-galet-brasillant",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/15289.w48h48.png",
"type": "Galet",
"lvl": "150",
"quantity": "3"
}
},
{
"Poudre glaciale": {
"id": "13154",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13154-poudre-glaciale",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/48292.w48h48.png",
"type": "Poudre",
"lvl": "190",
"quantity": "7"
}
},
{
"Poil d'aisselle de Missiz Frizz": {
"id": "13935",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13935-poil-aisselle-missiz-frizz",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/54691.w48h48.png",
"type": "Poil",
"lvl": "200",
"quantity": "9"
}
},
{
"Pédoncule de Mérulor": {
"id": "13978",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13978-pedoncule-merulor",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/119008.w48h48.png",
"type": "Champignon",
"lvl": "200",
"quantity": "6"
}
},
{
"Œil de Cycloïde": {
"id": "13988",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13988-oeil-cycloide",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/109603.w48h48.png",
"type": "Œil",
"lvl": "200",
"quantity": "30"
}
},
{
"Queue de Sinistrofu": {
"id": "13991",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13991-queue-sinistrofu",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/65764.w48h48.png",
"type": "Queue",
"lvl": "200",
"quantity": "3"
}
},
{
"Bandelette du Comte Harebourg": {
"id": "13995",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13995-bandelette-comte-harebourg",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/15831.w48h48.png",
"type": "Ressources diverses",
"lvl": "200",
"quantity": "1"
}
},
{
"Œil de verre": {
"id": "14145",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/14145-oeil-verre",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/109604.w48h48.png",
"type": "Œil",
"lvl": "200",
"quantity": "1"
}
}
],
"setId": 271
}
]
For the moment i extract data like that:
for (var i = 0; i < pets.length; i++) {
petsTable = {
name: pets[i].name,
level: pets[i].lvl,
type: pets[i].type,
description: pets[i].description,
imgUrl: pets[i].imgUrl,
url: pets[i].url,
condition: pets[i].condition,
recipe: pets[i].recipe
};
and to go on recipe i use an array :
var petsRecipe = [];
for (var x = 0; x < petsTable.recipe.length; x++) {
petsRecipe.push(petsTable.recipe[x]);
}
This array result :
Array(8) [Object, Object, Object, Object, Object, Object, Object, Object]
And an example of the first Object is :
0:
Galet brasillant:
id: "12740"
imgUrl: "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/15289.w48h48.png"
lvl: "150"
quantity: "3"
type: "Galet"
url: "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/...
But I can not collect the id or the "lvl", have you ideas ?
Thanks for your help
The problem with the recipe array is that every object it contains has a structure like this :
{
"Poudre glaciale": {
"id": "13154",
"lvl": "190",
"quantity": "7"
}
}
In other words, each object has one key (with a different name each time), and the object you want to reach is nested under this variable key, which makes it tricky to reach.
You can access the key name ("poudre glaciale") using Object.keys(obj)[0]. Then you can reach the sub-object easily :
const recipe = [{
"Galet brasillant": {
"id": "12740",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/12740-galet-brasillant",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/15289.w48h48.png",
"type": "Galet",
"lvl": "150",
"quantity": "3"
}
},
{
"Poudre glaciale": {
"id": "13154",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13154-poudre-glaciale",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/48292.w48h48.png",
"type": "Poudre",
"lvl": "190",
"quantity": "7"
}
},
{
"Poil d'aisselle de Missiz Frizz": {
"id": "13935",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13935-poil-aisselle-missiz-frizz",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/54691.w48h48.png",
"type": "Poil",
"lvl": "200",
"quantity": "9"
}
},
{
"Pédoncule de Mérulor": {
"id": "13978",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13978-pedoncule-merulor",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/119008.w48h48.png",
"type": "Champignon",
"lvl": "200",
"quantity": "6"
}
},
{
"Œil de Cycloïde": {
"id": "13988",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13988-oeil-cycloide",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/109603.w48h48.png",
"type": "Œil",
"lvl": "200",
"quantity": "30"
}
},
{
"Queue de Sinistrofu": {
"id": "13991",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13991-queue-sinistrofu",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/65764.w48h48.png",
"type": "Queue",
"lvl": "200",
"quantity": "3"
}
},
{
"Bandelette du Comte Harebourg": {
"id": "13995",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13995-bandelette-comte-harebourg",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/15831.w48h48.png",
"type": "Ressources diverses",
"lvl": "200",
"quantity": "1"
}
},
{
"Œil de verre": {
"id": "14145",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/14145-oeil-verre",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/109604.w48h48.png",
"type": "Œil",
"lvl": "200",
"quantity": "1"
}
}
]
const output = recipe.map( obj => {
let keyName = Object.keys(obj)[0]; // "Galet brasillant", "poudre glaciale", etc.
return obj[keyName]; // the object containing attributes
})
console.log(output[0])
Edit :
If you want the id of "Poudre glaciale", you have to do this :
First, filter the recipe array to keep only the object you want : recipe.filter( obj => Object.keys(obj)[0] === "Poudre glaciale")
Then, extract the first (and only) object from this filtered array with [0]
Then enter inside the "Poudre glaciale" key with ["Poudre glaciale"]
And then you can access the id
So the full solution :
const id = recipe.filter( obj => Object.keys(obj)[0] === "Poudre glaciale")[0]["Poudre glaciale"].id
This is my json object:
{
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
}
I want my output like this:
{
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"cats": [1,2] // this 1 and 2 is coming from categoriesservices array inside the category object i have id
}
How to do this using map function? I am new to javascript, which is good approach map or forloop?
See destructuring assignment, Array.prototype.map(), and JSON for more info.
// Input.
const input = {
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
}
// Categories => Objects to Cats => Ids.
const output = (input) => JSON.parse(JSON.stringify({
...input,
cats: input.categoryservices.map(({category: {id}}) => id),
categoryservices: undefined
}))
// Log.
console.log(output(input))
If you are not worried about original object immutability, then try this
obj['cats'] = obj['categoryservices'].map(cat => cat.category.id);
delete obj['categoryservices'];
console.log(obj);
I just use .map() on categoryservices array:
var output = {
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
};
output.cats = output.categoryservices.map((element) =>
element.category.id);
delete output.categoryservices;
console.log(JSON.stringify(output));
use .map() , it return value as array ! You want to change is categoryservices key only ! So delete that after you get wanted value ..
var output = {
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
};
output.cats = output.categoryservices.map(i => i.category.id );
delete output.categoryservices;
console.log(output);
Try this working demo :
var jsonObj = {
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
};
var arr = jsonObj.categoryservices.map(item => item.category.id)
jsonObj.cats = arr;
delete jsonObj.categoryservices;
console.log(jsonObj);
Try this
var testData={
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
}
testData.cats=[];
testData.categoryservices.forEach(function (item) {
testData.cats.push(item.category.id);
});
delete testData.categoryservices;
console.log(testData);
You can try using jquery each:
<div id="log"></div>
var conversation = {
'John': {
1: 'Test message 1',
2: 'Test message 2',
'Reply': {
3: 'Test message 3',
4: 'Test message 4'
}
},
'Jack': {
5: 'Test message 5',
6: 'Test message 6'
}
};
function iterate(obj) {
if (typeof obj === 'string') {
$('#log').append((obj + '<br/>'));
}
if (typeof obj === 'object') {
$.each(obj, function(key, value) {
iterate(value);
});
}
}
iterate(conversation);
Here is my JSON code. I'm storing this json in an array.
{
"kind": "urlshortener#url",
"id": "http://goo.gl/2FIrtF",
"longUrl": "http://hike.com/?utm_source=facebook",
"status": "OK",
"created": "2015-09-22T13:45:53.645+00:00",
"analytics": {
"allTime": {
"shortUrlClicks": "1",
"longUrlClicks": "1",
"referrers": [
{
"count": "1",
"id": "unknown"
}
],
"countries": [
{
"count": "1",
"id": "IN"
}
],
"browsers": [
{
"count": "1",
"id": "Chrome"
}
],
"platforms": [
{
"count": "1",
"id": "Macintosh"
}
]
},
"month": {
"shortUrlClicks": "1",
"longUrlClicks": "1",
"referrers": [
{
"count": "1",
"id": "unknown"
}
],
"countries": [
{
"count": "1",
"id": "IN"
}
],
"browsers": [
{
"count": "1",
"id": "Chrome"
}
],
"platforms": [
{
"count": "1",
"id": "Macintosh"
}
]
},
"week": {
"shortUrlClicks": "1",
"longUrlClicks": "1",
"referrers": [
{
"count": "1",
"id": "unknown"
}
],
"countries": [
{
"count": "1",
"id": "IN"
}
],
"browsers": [
{
"count": "1",
"id": "Chrome"
}
],
"platforms": [
{
"count": "1",
"id": "Macintosh"
}
]
},
"day": {
"shortUrlClicks": "0",
"longUrlClicks": "0"
},
"twoHours": {
"shortUrlClicks": "0",
"longUrlClicks": "0"
}
},
"result": {
"kind": "urlshortener#url",
"id": "http://goo.gl/2FIuvF",
"longUrl": "http://hike.com/?utm_source=facebook",
"status": "OK",
"created": "2015-09-22T13:45:53.645+00:00",
"analytics": {
"allTime": {
"shortUrlClicks": "1",
"longUrlClicks": "1",
"referrers": [
{
"count": "1",
"id": "unknown"
}
],
"countries": [
{
"count": "1",
"id": "IN"
}
],
"browsers": [
{
"count": "1",
"id": "Chrome"
}
],
"platforms": [
{
"count": "1",
"id": "Macintosh"
}
]
},
"month": {
"shortUrlClicks": "1",
"longUrlClicks": "1",
"referrers": [
{
"count": "1",
"id": "unknown"
}
],
"countries": [
{
"count": "1",
"id": "IN"
}
],
"browsers": [
{
"count": "1",
"id": "Chrome"
}
],
"platforms": [
{
"count": "1",
"id": "Macintosh"
}
]
},
"week": {
"shortUrlClicks": "1",
"longUrlClicks": "1",
"referrers": [
{
"count": "1",
"id": "unknown"
}
],
"countries": [
{
"count": "1",
"id": "IN"
}
],
"browsers": [
{
"count": "1",
"id": "Chrome"
}
],
"platforms": [
{
"count": "1",
"id": "Macintosh"
}
]
},
"day": {
"shortUrlClicks": "0",
"longUrlClicks": "0"
},
"twoHours": {
"shortUrlClicks": "0",
"longUrlClicks": "0"
}
}
}
}
In the above JSON, how can we get the existence of analytics -> day -> countries?
I want to know whether the countries exists in day or not first, if it's not, show some value. If it is there, it will try to fetch the count of particualr country.
I'm trying this from last 5 hours without any luck.
if(arr.analytics.day.countries !== undefined) {
function thingscount(arr, platf) {
var x = arr.analytics.day.countries.map(function(el) {
return (platf.indexOf(el.id) != -1) ? parseInt(el.count) : 0; });
var count = 0;
for (var i = 0; i < x.length; i++) count += x[i];
return count;
}
var one = thingscount(arr, ["US"]);
}else{
var one = 0;
}
The above code is working fine if there is countries in day, but sometimes, in my JSON there will be no platforms part, in that case it's giving me
Uncaught TypeError: Cannot read property 'map' of undefined
I need a way to check if the platforms exist, if it's go for a count, if it's not give some other value to the variable.
UPDATE :
I'm using this below code to get the count of IN.
When it has IN key and value, it's giving me the result. But when it don't has the IN key, it's showing 'undefined count' error.
var month_inclicks = arr.analytics.month.countries.filter(function(el) { return el.id == "IN"; })[0].count;
How can we set a default value if the key we are looking for is not exists?
While that isn't JSON, I'm assuming it's a javascript object. That being said, you'll want to look into utilizing the hasOwnProperty method or the in keyword.
Example:
if (arr.total.limited.hasOwnProperty('platforms')) { //do stuff
or
if ('platforms' in arr.total.limited) { //do something
I have corrected your JSON. use hasOwnProperty as #CollinD suggested
var arr = {
total: {
limited: {
things: "451",
platforms: [{
count: "358",
id: "Windows"
}, {
count: "44",
id: "X11"
}, {
count: "42",
id: "Macintosh"
}, {
count: "2",
id: "Linux"
}, {
count: "1",
id: "iPhone"
}, {
count: "1",
id: "iPod"
}]
}
}
};
Object.prototype.hasOwnProperty()
console.log(arr.total.limited.hasOwnProperty('platforms'));
DEMO
For the record, you can roll the map and the count in your 'thingscount' function into one operation by using reduce:
var getCount = function getCount( ary, find ) {
return ary.reduce(function ( acc, record) {
if (find.indexOf(record.id) !== -1) acc += parseInt(record.count, 10);
return acc;
}, 0);
};
Usage inline:
if (arr.analytics.day.hasOwnProperty('countries')) {
var find = ['IN'],
count = arr.analytics.day.countries.reduce(function ( acc, record) {
if (find.indexOf(record.id) !== -1) acc += parseInt(record.count, 10);
return acc;
}, 0);
}
Or with the function:
if (arr.analytics.day.hasOwnProperty('countries')) {
var count = getCount(arr.analytics.day.countries, ['US','IN']);
}