Select particular field with condition satisfied in child in mongoDB using sails - javascript

I am having a mongoDB collection and the JSON looks like
[{
class : "I",
subject : "Maths",
students: [{
name : "John",
roll_no : "1001",
marks : "65",
is_passed : "true"
},
{
name : "Leo",
roll_no : "1002",
marks : "48",
is_passed : "false"
}]
}]
I am able to get the data using the command
My_Table_Name.find({}, {fields:{
'class' : 1,
'students':1
}
})
.populate('students',{
select : ['name', 'is_passed']
})
by this I can get the output as
[{
class : "I",
students : [{
name : "John",
is_passed : "true"
},
{
name : "Leo",
is_passed : "false"
}]
}]
but I need to get is_passed key only when it has true value,
my expected JSON is
[{
class : "I",
students : [{
name : "John",
is_passed : "true"
},
{
name : "Leo"
}]
}]
here in class I Leo has failed, so I do not need that field.
Please help to get through this problem, thanks in advance

Related

Access title inside id

I am having trouble to access title inside an ID object.
I want to access item.title. But i am not able to give a name to the object ID.
I tried doing order.cart.items.item.title
"_id" : ObjectId("5d60d1752cda6403e4f868af"),
"created_at" : ISODate("2019-08-24T05:55:34.741Z"),
"user" : ObjectId("5d60d00e4c865312ccf3f18a"),
"cart" : {
"items" : {
"5d60cddb69f460191c680e96" : {
"item" : {
"_id" : "5d60cddb69f460191c680e96",
"imagePath" : "https://dks.scene7.com/is/image/GolfGalaxy/18NIKWRMX270XXXXXLFS_Black_Cream?wid=1080&fmt=jpg",
"title" : "Nike ",
"description" : "Nike Airmax",
"price" : 10,
"category" : "shoes",
"__v" : 0
},
"qty" : 1,
"price" : 10
}
},
"totalQty" : 1,
"totalPrice" : 10
},
You need to use Object.values for that, because of the ID. This allows you to get the object with the key of 5d60cddb69f460191c680e96 without the key:
Object.values(order.cart.items)[0].item.title
const data = {
"cart" : {
"items" : {
"5d60cddb69f460191c680e96" : {
"item" : {
"_id" : "5d60cddb69f460191c680e96",
"imagePath" : "https://dks.scene7.com/is/image/GolfGalaxy/18NIKWRMX270XXXXXLFS_Black_Cream?wid=1080&fmt=jpg",
"title" : "Nike ",
"description" : "Nike Airmax",
"price" : 10,
"category" : "shoes",
"__v" : 0
},
"qty" : 1,
"price" : 10
}
},
"totalQty" : 1,
"totalPrice" : 10
}};
for (let id in data.cart.items)
console.log(data.cart.items[id].item.title);
You can simply achieve this by getting key name of an object using Object.keys() methods, This methods returns an array of key names
const obj = { id: 1 };
const keysArray = Object.keys(obj);
console.log(keysArray);. // ["id"]
In your case only one keys are present in the object, So we can directly get that name with index 0 (Object.keys(obj)[0])
Check below snippet
const cart ={
"items": {
"5d60cddb69f460191c680e96": {
"item": {
"_id":
"5d60cddb69f460191c680e96",
"imagePath": '',
"title": "Nike ",
"description": "Nike",
"price": 10,
"category": "shoes",
"__v": 0
},
"qty": 1,
"price": 10
}
}
};
const id =
Object.keys(cart.items)[0];
console.log(
cart.items[id].item.title
);

Looping Through Nested JSON with Nested Child Searches

I have a JSON structure that looks like this:
"benefitValues" : [ {
"changeDate" : "2017-10-13T20:26:13.000+0000",
"changeUserName" : "aaaa",
"numericValue" : 20,
"value" : "20",
"amountType" : {
"allowCustomDataFlg" : false,
"dataType" : "Percent",
"defaultTypeFlg" : true,
"defaultValue" : "Unlimited",
"description" : null,
"maxValue" : null,
"minValue" : null,
"name" : "LIST",
"benefit" : {
"category" : "Facility Services",
"name" : "Single Limit",
"networkStatus" : "IN_NETWORK",
"planType" : "MedicalPlan",
"sortOrder" : 20,
"subcategory" : "Acupuncture Treatment",
"subcategorySortOrder" : 6
}
}
}]
Based on the string "Acupuncture Treatment", I need to extract the the value and the datatype. The dataset is very large, with hundreds of subcategories. I cannot find a good way to search through this data. I tried json-path and advanced-json-path, but if I do a search on a child element, there is no way for me to return the parents. I want my output to look like this:
{
"Subcategory" : "Acupuncture Treatment",
"Value" : "20",
"Type" : "Percent"
}
I was hoping there was an easy way to do this with an existing library, or at least with a simple loop.
This will find the matching element frombenefitValues, and transform the element into the format you're expecting:
var benefitValues = [{
"changeDate": "2017-10-13T20:26:13.000+0000",
"changeUserName": "aaaa",
"numericValue": 20,
"value": "20",
"amountType": {
"allowCustomDataFlg": false,
"dataType": "Percent",
"defaultTypeFlg": true,
"defaultValue": "Unlimited",
"description": null,
"maxValue": null,
"minValue": null,
"name": "LIST",
"benefit": {
"category": "Facility Services",
"name": "Single Limit",
"networkStatus": "IN_NETWORK",
"planType": "MedicalPlan",
"sortOrder": 20,
"subcategory": "Acupuncture Treatment",
"subcategorySortOrder": 6
}
}
}];
// Find the element
let treatment = benefitValues.find((item) => item.amountType.benefit.subcategory === 'Acupuncture Treatment');
let result = {
Value: treatment.value,
Subcategory: treatment.amountType.benefit.subcategory,
Type: treatment.amountType.dataType
}
console.log(result);
You can search through your data set and pull out only the items that match your string by using .filter. That would give you the entire object, so then you can use .map to transform it to the structure you want.
Or if you're only interested in the first result, you can use .find instead.
const json = {"benefitValues" : [{
"changeDate" : "2017-10-13T20:26:13.000+0000",
"changeUserName" : "aaaa",
"numericValue" : 20,
"value" : "20",
"amountType" : {
"allowCustomDataFlg" : false,
"dataType" : "Percent",
"defaultTypeFlg" : true,
"defaultValue" : "Unlimited",
"description" : null,
"maxValue" : null,
"minValue" : null,
"name" : "LIST",
"benefit" : {
"category" : "Facility Services",
"name" : "Single Limit",
"networkStatus" : "IN_NETWORK",
"planType" : "MedicalPlan",
"sortOrder" : 20,
"subcategory" : "Acupuncture Treatment",
"subcategorySortOrder" : 6
}
}
}]};
// With filter/map
const result = json.benefitValues
.filter(val => val.amountType.benefit.subcategory === "Acupuncture Treatment")
.map(val => ({Subcategory: val.amountType.benefit.subcategory, Value: val.value, Type: val.amountType.dataType}));
console.log(result)
// With find / manual transform:
const singleFullResult = json.benefitValues
.find(val => val.amountType.benefit.subcategory === "Acupuncture Treatment")
const singleResult = {
Subcategory: singleFullResult.amountType.benefit.subcategory,
Value: singleFullResult.value,
Type: singleFullResult.amountType.dataType
}
console.log(singleResult)
You can use Array.prototype.filter() combined with Array.prototype.map() and create an array of object with the structure you need. Here's an example:
let myArray = [{
"changeDate": "2017-10-13T20:26:13.000+0000",
"changeUserName": "aaaa",
"numericValue": 20,
"value": "20",
"amountType": {
"allowCustomDataFlg": false,
"dataType": "Percent",
"defaultTypeFlg": true,
"defaultValue": "Unlimited",
"description": null,
"maxValue": null,
"minValue": null,
"name": "LIST",
"benefit": {
"category": "Facility Services",
"name": "Single Limit",
"networkStatus": "IN_NETWORK",
"planType": "MedicalPlan",
"sortOrder": 20,
"subcategory": "Acupuncture Treatment",
"subcategorySortOrder": 6
}
}
}];
let ret = myArray
.filter(arr => arr.amountType.benefit.subcategory === 'Acupuncture Treatment')
.map(arr => {
return {
Subcategory: arr.amountType.benefit.subcategory,
Value: arr.value,
Type: arr.amountType.dataType
};
});
console.log(ret);
First the filter function will filter your array and return only the items related to 'Acupuncture Treatment', then the map function, that receives as a parameter a function that will be executed for each item inside the array and it will return a new structure, will return only the fields you need.

how to use value as key in mongodb

Given this as output of mongo find command
{
"cust" : NumberInt(8388),
"key" : "T_SUB_CAT",
"value" : "98",
"tag1" : "T_RECENT_SUB_CAT_1"
},{
"cust" : NumberInt(8388),
"key" : "T_SUB_CAT",
"value" : "109",
"tag1" : "T_RECENT_SUB_CAT_2"
},{
"cust" : NumberInt(8388),
"key" : "T_SUB_CAT",
"value" : "6",
"tag1" : "T_RECENT_SUB_CAT_3"
}
how to use aggregation and $project to get result like this
{
"cust" : NumberInt(8388),
"T_RECENT_SUB_CAT_1" : "98",
"T_RECENT_SUB_CAT_2" : "109",
"T_RECENT_SUB_CAT_3" : "6"
}
please help me using project / aggregate
thanks a lot
put all result in a var say cust2,
while(cust2.hasNext()){
var document = cust2.next(); db.<collection>.update(
{ cust: document.cust, tag1:document.tag1 },
{ cust:document.cust , tag1:document.tag1 ,
key:document.key, value:document.value },
{upsert:true}
) }

How to go through JSON data to create a list, even the children?

I have a JSON object that I need to create a list out of.
I would be able to do it fine but each object can have children. It looks something like this :
{
"Boys" :
[
{
"name" : "Fred",
"age" : "65",
"children" : [{
"name" : "dave",
"age" : "24",
"children" : []
}, {
"name" : "cliff",
"age" : "32",
"children" : []
}
]
},
{
"name" : "jon",
"age" : "46",
"children" : [{
"name" : "jess",
"age" : "26",
"children" : []
}, {
"name" : "gloria",
"age" : "19",
"children" : []
}
]
}
],
"Girls" :
[
{
"name" : "Jane",
"age" : "65",
"children" : [{
"name" : "dave",
"age" : "24",
"children" : []
}, {
"name" : "grace",
"age" : "32",
"children" : []
}
]
},
{
"name" : "ariana",
"age" : "46",
"children" : [{
"name" : "jessy",
"age" : "28",
"children" : []
}, {
"name" : "niki",
"age" : "19",
"children" : []
}
]
}
]
}
I'd be able to go through it fine in a for-loop but I'm unsure how to go through the children too.
Basically I want to go through each element and create a list item with the text being the name of the object I am currently at.
So for the JSON above it would be something like :
-Boys
-Fred
-Dave
-Cliff
-Jon
-Jess
-Gloria
-Girls
-Jane
-Dave
-Grace
-Ariana
-Jessy
-Niki
After I create this list I will be using JSTree to format it, any help is appreciated :)
You need a recursive function, a function that calls itself until something happens. In your case, you need a function that goes through a list of people. For each person, it'd paint the name, then would check if that person has children. If it does, then calls the function again, passing it the list of children.
Something like this:
var renderList = function(list){
var $list = $('<ul>');
$.each(list, function(i, element){
var $child = $('<li>'+element.name+'</li>');
if (element.children.length > 0) {
$child.append(renderList(element.children));
}
$list.append($child);
});
return $list;
};
$('#boys').append(renderList(data.Boys)); // Start list of boys
$('#girls').append(renderList(data.Girls)); // Start list of girls
Working example here http://jsfiddle.net/zbm778ag/

How to match a document with the value of an object attribute in Mongodb

I'm trying to match some document in mongoDB:
My Document model :
profile: {
languages: [
{"name": "French", "level": 1},
{"name": "English", "level": 2},
{"name": "Spanish", "level": 4}
]
}
What I (can) have to search my result set:
lang = ["French", "English"];
objLang = [
{name: "French"},
{name: "English"}
];
What I need is to db.find() all documents that match at least one of the languages, for example :
profile.languages.name = "French"
or
profile.languages.name = "English"
WHat I mean is that if I have French or English in my option set, I need to get all the users who have a element of their languages array where name match one of my options, no matter the level of the languages.
So, unless I'm wrong, I can't do
db.find({"profile.languages": {$in: [{name: "French"}, {name: "English"}]});
How would you proceed ?
Thanks a lot.
David
Actually, you were almost right:
db.collection.find({"profile.languages.name":{$in: ["French","English"]} })
Since profile.languages is an array of subdocuments, you can call in for one of the subdocument's keys and the subsequent query gets mapped to all subdocuments containing that key.
However, without proper indexing, an added .explain() shows something pretty ugly:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.languages",
"indexFilterSet" : false,
"parsedQuery" : {
"profile.languages.name" : {
"$in" : [
"English",
"French"
]
}
},
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"profile.languages.name" : {
"$in" : [
"English",
"French"
]
}
},
"direction" : "forward"
},
"rejectedPlans" : [ ]
}
}
(serverInfowas ommited).
So in order to make this query efficient, you need to create an index over the field you want to query:
db.languages.ensureIndex({"profile.languages.name":1})
An added explain now tells us that the matching documents are identified via the index:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.languages",
"indexFilterSet" : false,
"parsedQuery" : {
"profile.languages.name" : {
"$in" : [
"English",
"French"
]
}
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"profile.languages.name" : 1
},
"indexName" : "profile.languages.name_1",
"isMultiKey" : true,
"direction" : "forward",
"indexBounds" : {
"profile.languages.name" : [
"[\"English\", \"English\"]",
"[\"French\", \"French\"]"
]
}
}
},
"rejectedPlans" : [ ]
},
"ok" : 1
}
You could try using the dot notation to access both the elements of an array and to access the fields of an embedded document:
db.find({
"profile.languages.name": {
"$in": ["French", "English"]
}
});
Please try the below query :
Solution 1 :
db.collection.aggregate([
{
$unwind:"$profile.languages"
},
{
$match:{"profile.languages.name":{"$in":["French", "English"]}}
},
{
$group:{_id: "$_id", profile:{"$push":"$profile.languages"}}
}
])
Solution 2 :
db.collection.find(
{
"profile.languages.name":
{
"$in": [ "English", "French"]
}
}
);

Categories

Resources