How to combine JSON objects with equal values within Backbone.js - javascript

I am trying to display multiple "unread" alerts, but need to attach the organizations label to it if the organizations id is equal to the unread domainId.
How can I acheive this while displaying the results in a handlebars #each function?
JSON
"alerts" : {
"organizations" : [ {
"id" : 165,
"label" : "Label #1"
}, {
"id" : 170,
"label" : "Label #2"
}],
"unread" : [ {
"id" : 20022,
"domainId" : 170,
"created" : "2015-10-13T16:48:08Z",
}, {
"id" : 20022,
"domainId" : 165,
"created" : "2015-10-13T16:48:08Z",
}]
};
Backbone.js:
context: function() {
var d = this.options.data
return {
welcomeAlerts: d.alerts,
welcomeOrg: d.alerts.organizations.label
}
},
Handlebars//HTMl
{{#each welcomeAlerts.unread}}
<li class="alert-item stripe-list-item">
<h4 class="org">{{welcomeOrg}}</h4>
<h4 class="timestamp">{{created}}</h4>
</li>
{{/each}}

Simply transform the data beforehand
var data = {
"alerts" : {
"organizations" : [ {
"id" : 165,
"label" : "Label #1"
}, {
"id" : 170,
"label" : "Label #2"
}],
"unread" : [ {
"id" : 20022,
"domainId" : 170,
"created" : "2015-10-13T16:48:08Z",
}, {
"id" : 20022,
"domainId" : 165,
"created" : "2015-10-13T16:48:08Z",
}]
}
};
var organizationDict = _.groupBy(data.alerts.organizations, 'id');
var unreadWithOrganizations = _(data.alerts.unread)
.map((message) => {
return {
...message,
organization: organizationDict[message.domainId]
}
})
.value();
and display your data
{{#each unreadWithOrganizations}}
<li class="alert-item stripe-list-item">
<h4 class="org">{{organization.label}}</h4>
<h4 class="timestamp">{{created}}</h4>
</li>
{{/each}}
Demo: http://jsbin.com/sadoluhepu/edit?js,console
I've made an example using lodash library and es6. You might want to stick with ES6 and underscore, which implementation might differ.

Related

How to find data on MongoDB by passing part of array objects

I tried to create an API for filtering the products by sending an array of objects as filters.
this is my Product schema:
const mongoose = require("mongoose");
const { s, rs, rn, rref, ref } = require("../utils/mongo");
let schema = new mongoose.Schema(
{
user: rref("user"),
name: rs,
description: s,
images: [s],
price: rn,
category: ref("category"),
filters: [
{
parent: ref("filter"),
value: s,
name: s,
},
],
subFilter: [
{
parent: s,
value: s,
title: s,
},
],
},
{ timestamps: true }
);
module.exports = mongoose.model("product", schema);
and this one is what I want to send as body to the API
{
category: '62445c3d922d127512867245'
filters: [
{ name: 'filter name 1', value: '62445c3d922d127512861236' },
{ name: 'filter name 2', value: '62445c3d922d127512861458' },
.....
]
}
as you see I want to filter my products based on category Id and an array of filter objects. I tried to write this query but it return an empty array.
this is my query:
filter: async (req, res) => {
try {
const { category, filters } = req.body;
const products = await Product.find({
category,
filters: {
$in: filters,
},
});
res.status(200).json(products);
} catch (err) {
res.status(500).json(err);
}
},
what stored on db
{
"_id" : ObjectId("62643acf19636d7db1804cb3"),
"images" : [
"image-1650735823476۸.jpg"
],
"user" : ObjectId("622606af0f40cb8ea37383dc"),
"name" : "شیر توپی 2 اینچ کلاس 150 پیشگام",
"description" : " برند پیشگام با مدارک و تاییدیه ",
"price" : NumberInt(5000000),
"category" : ObjectId("62445c4d922d127512867246"),
"filters" : [
{
"_id" : ObjectId("62643acf19636d7db1804cb4"),
"parent" : ObjectId("6264307f19636d7db1804b77"),
"value" : "626430bb19636d7db1804b78",
"name" : "Valve Type"
},
{
"_id" : ObjectId("62643acf19636d7db1804cb5"),
"parent" : ObjectId("6264319819636d7db1804b7b"),
"value" : "6264319819636d7db1804b7e",
"name" : "Body Type"
},
{
"_id" : ObjectId("62643acf19636d7db1804cb6"),
"parent" : ObjectId("626431ef19636d7db1804b82"),
"value" : "626431ef19636d7db1804b83",
"name" : "Bore Type"
},
{
"_id" : ObjectId("62643acf19636d7db1804cb7"),
"parent" : ObjectId("6264328519636d7db1804b85"),
"value" : "6264328519636d7db1804b86",
"name" : "Material Type"
},
{
"_id" : ObjectId("62643acf19636d7db1804cb8"),
"parent" : ObjectId("626435de19636d7db1804c10"),
"value" : "626439b619636d7db1804ca7",
"name" : "Trim Material"
},
{
"_id" : ObjectId("62643acf19636d7db1804cb9"),
"parent" : ObjectId("6264367919636d7db1804c17"),
"value" : "6264367919636d7db1804c18",
"name" : "End Conection"
},
{
"_id" : ObjectId("62643acf19636d7db1804cba"),
"parent" : ObjectId("626436a719636d7db1804c1f"),
"value" : "6264378119636d7db1804c28",
"name" : "Size"
},
{
"_id" : ObjectId("62643acf19636d7db1804cbb"),
"parent" : ObjectId("6264389219636d7db1804c6d"),
"value" : "6264389219636d7db1804c6f",
"name" : "Class / Pressure"
}
],
"subFilter" : [
{
"_id" : ObjectId("62643acf19636d7db1804cbc"),
"parent" : "6264328519636d7db1804b85",
"value" : "626433b919636d7db1804b93",
"title" : "Body Material"
}
],
"createdAt" : ISODate("2022-04-23T17:43:43.421+0000"),
"updatedAt" : ISODate("2022-04-23T17:53:29.016+0000"),
"__v" : NumberInt(0)
}
Consider this shrunk down set of inputs that capture the essence of the question. The comments "give away" what we are going to try to find and why. We only show one value for category because matching on that is trivial and not the interesting part of the query.
[
{
"category" : ObjectId("62445c4d922d127512867246"),
"filters" : [
// Matching Valve/value; include this doc
{"name" : "Valve", "value" : "626430bb19636d7db1804b78"},
// ALSO match Body/value; include this doc (but needs only 1 match)
{"name" : "Body", "value" : "6264319819636d7db1804b7e"}
]
}
,{
"category" : ObjectId("62445c4d922d127512867246"),
"filters" : [
// Not target value for Valve name (..79 instead of ...78):
{"name" : "Valve", "value" : "626430bb19636d7db1804b79"},
// ...but correct value for Body, so include this doc
{"name" : "Body", "value" : "6264319819636d7db1804b7e"}
]
}
,{
"category" : ObjectId("62445c4d922d127512867246"),
// No matching Valve or Body so this whole doc is ignored.
"filters" : [
{"name" : "Valve", "value" : "626430bb19636d7db1804b79"},
{"name" : "Body", "value" : "6264319819636d7db1804b7f"}
]
}
,{
"category" : ObjectId("62445c4d922d127512867246"),
// Not even name matches so ignore this too:
"filters" : [
{"name" : "Pipe", "value" : "6264319819636d7db1804eee"}
]
}
]
Assume also we set up inputs coming from the API like this, in their native form i.e. strings NOT ObjectId:
var targ_cat = '62445c4d922d127512867246';
var any_one_of = [
{ name: 'Valve', value: '626430bb19636d7db1804b78' },
{ name: 'Body', value: '6264319819636d7db1804b7e'}
];
We will use $filter as our main function but to do so, we must convert the incoming material into a form required by $filter.
// Convert inbound array of any_one_of into a something designed to work
// in the $filter function by comparing each name/value entry in the
// filters field to the item presented in $$this, meaning take:
// { name: 'Valve', value: '626430bb19636d7db1804b78' },
// and turn it into:
// {$and: [ {$eq:['Valve','$$this.name']}, {$eq:['62643...','$$this.value']} ] }
// Since any one of the entries is considered a hit, we package it all
// into an $or wrapper, not $and.
var or_list = [];
any_one_of.forEach(function(f) {
or_list.push( {$and: [
{$eq:[f['name'], '$$this.name']},
{$eq:[f['value'], '$$this.value']}
]});
});
var or_expr = {$or: or_list};
Now we are ready to query mongoDB:
db.foo.aggregate([
// Get this out of the way quickly; note we must make a new ObjectId!
{$match: {'category': new ObjectId(targ_cat)}}
// The interesting part of the query:
,{$addFields: {filters: {$filter: {input: '$filters', cond: or_expr}}}}
// Only keep those items where $filter found at least one of the
// targets:
,{$match: {$expr: {$gt:[{$size: '$filters'},0]} }}
]);

How to extract data from Firebase realtime database JSON-export

I have a Firebase realtime-database export-json that has nested informations, that I would like to extract. The structure of the JSON looks like this:
{
"users" : {
"024w97mv8NftGFY8THfQIU6PhaJ3" : {
"email" : "xxx",
"id" : "024w97mv8NftGFY8THfQIU6PhaJ3",
"name" : "xxx",
"items" : {
"-LQL9n-r9BGdo3HJZ2sk" : {
"disliked" : true,
"id" : 396,
"name" : "Aaa"
},
"-LQL9oO63nH-QW2w6zz0" : {
"liked" : true,
"id" : 3674,
"name" : "Bbb"
}
}
},
"0ERLT5DLRvbZUnjlnM7Ow0qItpz2" : {
"email" : "zzz",
"id" : "0ERLT5DLRvbZUnjlnM7Ow0qItpz2",
"name" : "zzz",
"items" : {
"-LIZnriSVQMzqTsPFNYa" : {
"id" : 396,
"liked" : true,
"name" : "Aaa"
},
"-LIZnrzOuk4WyjqEiLG8" : {
"disliked" : true,
"id" : 4805,
"name" : "Ccc"
}
}
}
}
}
What I need to achieve is getting a list of all liked item-names, and ideally counting how often an item is liked.
Is there a simple tool or script to do that? Ruby or Javascript would be preferred. Thanks a lot!
You can parse your JSON data in ruby like below
result_hash = JSON.parse(result)
result_ary = result_hash["users"].collect do |k,v|
v["items"].values.select{|v1| v1["liked"] == true }
end
result_data = result_ary.flatten
result of parsing
=> [{"liked"=>true, "id"=>3674, "name"=>"Bbb"}, {"id"=>396, "liked"=>true, "name"=>"Aaa"}]
Now its very easy for getting your required result
result_data.collect{|x| x["name"] }
=> ["Bbb", "Aaa"]
result_data.count {|x| x["name"] == "Aaa"}
=> 1
result_data.count {|x| x["name"] == "Bbb"}
=> 1

Find and remove nested level

I want to find and remove the value, where my id is "5cc6d9737760963ea07de411"
my data:
[
{
"products" : [ {
"id" : "5cc6d9737760963ea07de411",
"quantity" : 1,
"totalPrice" : 100,
},
{
"id" : "5cc6d9737760963ea07de412",
"quantity" : 2,
"totalPrice" : 200,
}
],
"isCompleted" : false,
"_id" : "5cc7e4096d7c2c1f03570a2f"
},
{
"products" : [{
"id" : "5cc6d9737760963ea07de414",
"quantity" : 1,
"totalPrice" : 100,
},
{
"id" : "5cc6d9737760963ea07de4133",
"quantity" : 2,
"totalPrice" : 200,
}
],
"isCompleted" : false,
"_id" : "5cc7e4096d7c2c1f03570a2f"
}
]
i tried:
Schema.findOneAndUpdate({"products.id": "5cc6d9737760963ea07de411"},
{ $pull: {"products.$.id": "5cc6d9737760963ea07de411" })
but it's not working.
Now you don't need to use .dot notation. Instead you need to use "absolute" object structures:
Schema.findOneAndUpdate(
{ "products.id": "5cc6d9737760963ea07de411" },
{ "$pull": { "products": { "id": "5cc6d9737760963ea07de411" }}}
)

unable to fetch value from JSON array in javascript

I'm unable to fetch JSON value to check if the person is wearing glasses while taking photo, the value relies in four arrays: photos, tags, attributes and glasses, I want to check the value "value" is true or false. I use alert() to test if value fetched but nothing comes out. I don't know which part gets wrong
I use JavaScript to fetch the JSON value as follows:
var facesDet = $.getJSON( APIdetect, function() {
console.log( "success" );
console.log(facesDet);
})
.done(function (facesDet, tid) {
var VALUEIWANT = facesDet.photos[0].tags[0].attributes[0].gender[0].value;
});
The JSON value looks as follows:
{
"photos" : [
{
"url" : "http://tinyurl.com/673cksr",
"pid" : "F#0c95576847e9cd7123f1e304476b59ae_59ec9bb2ad15f",
"width" : 375,
"height" : 409,
"tags" : [
{
"tid" : "TEMP_F#0c95576847e9cd7123f1e304b1dcbe53_59ec9bb2ad15f_56.53_40.83_0_1",
"recognizable" : true,
"confirmed" : false,
"manual" : false,
"width" : 30.67,
"height" : 28.12,
"center" : { "x" : 56.53, "y" : 40.83},
"eye_left" : { "x" : 66.93, "y" : 33.99},
"eye_right" : { "x" : 51.73, "y" : 33.99},
"yaw" : -16,
"roll" : 0,
"pitch" : 0,
"attributes" : {
"face" : { "value" : "true", "confidence" : 82 },
"gender" : { "value" : "female", "confidence" : 80 },
"glasses":{"value" : "true", "confidence" : 100},
"dark_glasses":{"value" : "true", "confidence" : 72},
"smiling":{"value" : "false", "confidence" : 35}
}
}
]
}
],
"status" : "success",
"usage" : {
"used" : 1,
"remaining" : 99,
"limit" : 100,
"reset_time_text" : "Fri, 21 September 2012 12:57:19 +0000",
"reset_time" : 1348232239
}
}
You tryed to take value from gender like from array:
var VALUEIWANT = facesDet.photos[0].tags[0].attributes[0].gender[0].value;
But in your json its object, so you should use:
var VALUEIWANT = facesDet.photos[0].tags[0].attributes.gender.value;
Your access is wrong. You have an object, but you treat it like an array
var VALUEIWANT = facesDet.photos[0].tags[0].attributes[0].gender[0].value;
// ^^^ and ^^^
right access:
var VALUEIWANT = facesDet.photos[0].tags[0].attributes.gender.value;
data:
"attributes" : {
"face" : { "value" : "true", "confidence" : 82 },
"gender" : { "value" : "female", "confidence" : 80 },
"glasses":{"value" : "true", "confidence" : 100},
"dark_glasses":{"value" : "true", "confidence" : 72},
"smiling":{"value" : "false", "confidence" : 35}
}
try this one.
facesDet.photos[0].tags[0].attributes.gender.value
getJSON return a promise not the response, you need to use this code:
$.getJSON( APIdetect, function(facesDet) {
console.log( "success" );
console.log(facesDet);
})

Mongoose structure aggregation output without field names

I am using aggregate to paginate data from subdocuments. The subdocuments don't have a strict schema so they can be different for each document, this is making it difficult for me to structure my output as I don't know the field names for the subdocuments.
What I am using
Mongo 3.0.0
Node 0.10.33
Mongoose 3.9.7
My models
var BodySchema = new Schema({random: String},{strict:false});
var FeedSchema = new Schema({
name: String,
body:[BodySchema]
});
My data looks like this
[{
_id:"...",
name:"Power Rangers feed",
body:[
{
"_id":"...",
"name" : "Jason",
"colour" : "Red",
"animal" : "T-rex"
},
{
"_id":"...",
"name" : "Billy",
"colour" : "Blue",
"animal" : "Triceratops"
},
{
"_id":"...",
"name" : "Zach",
"colour" : "Black",
"animal" : "Mastadon"
}
]
},
{
_id:"...",
name:"Transformers feed",
body:[
{
"_id":"...",
"name" : "Optimus Prime",
"team" : "Autobots",
"class" : "leader"
"alt-mode" : "truck"
},
{
"_id":"...",
"name" : "Bumblebee",
"team" : "Autobots",
"class" : "scout"
"alt-mode" : "VW Beetle"
},
{
"_id":"...",
"name" : "Blaster",
"team" : "Autobots",
"class" : "Commmunicator"
"alt-mode" : "Sterio"
},
{
"_id":"...",
"name" : "Hotrod",
"team" : "Autobots",
"class" : "Warrior"
"alt-mode" : "Car"
}
]
}]
My current aggregate code looks like this
feed.aggregate([
{'$match':{_id:id('550234d3d06039d507d238d8')}},
{'$unwind':'$body'},
{'$skip':2},
{'$limit':2},
{
'$project': {
'_id':"$body._id",
'body': "$body"
}
},
], function(err, result){
if(err){return(res.send(500, err))}
res.send(result);
});
My current result looks like this
[{
_id:"...",
body:{
"_id":"...",
"name" : "Blaster",
"team" : "Autobots",
"class" : "Commmunicator"
"alt-mode" : "Sterio"
}
},
{
_id:"...",
body:{
"_id":"...",
"name" : "Hotrod",
"team" : "Autobots",
"class" : "Warrior"
"alt-mode" : "Car"
}
}]
My desired result looks like this
[
{
"_id":"...",
"name" : "Blaster",
"team" : "Autobots",
"class" : "Commmunicator"
"alt-mode" : "Sterio"
},
{
"_id":"...",
"name" : "Hotrod",
"team" : "Autobots",
"class" : "Warrior"
"alt-mode" : "Car"
}
]
My Question
How can I achieve my desired result structure.
So, you are going to hate this, but this is just how the $project and the $group stages in the aggregation pipeline work. You need to specify all of the fields that you want in the output "explicitly". Therefore:
feed.aggregate([
{'$match':{_id:id('550234d3d06039d507d238d8')}},
{'$unwind':'$body'},
{'$skip':2},
{'$limit':2},
{
'$project': {
'_id':"$body._id",
'name': '$body.name',
'team': '$body.team',
'class': '$body.alt-mode'
}
},
], function(err, result){
That really is the only way to do it.
There really is a strong reasoning behind that though, and most of the principles are backed up in SQL SELECT, with the exception of the * "wildcard" where applicable.
The general premise is that this is analogous to unix pipe in general operation so if you think like:
grep | awk | sed
Then the operations seem more logical in structure.

Categories