I'm trying to display a piechart using the Highchart package for Meteor.
I've got it working with a static data source, like this:
series: [{
type: 'pie',
name: 'Sales',
data:
[
["Norway", 123123.32],
["Canada", 1977844.86],
["France", 2644017.71],
["Denmark", 28954612.34],
["United Kingdom", 3391712.21],
["United States", 9389789.51]
]
}]
in the series part of the .js of the template file.
But when I'm trying to use MongoDb's find statement it either shows no data or the report is showing up weirdly, I guess this is due to the formatting of the data resulted from the find query.
My data in the collection is looking something like this:
{ "_id" : "HsgEBrrSvBp6qzp8Q", "0" : "Norway", "1" : 9061000.58 }
{ "_id" : "5dvtddEogj6d5Zw7D", "0" : "Canada", "1" : 1977844.86 }
{ "_id" : "6XmfgjBG4dupes3ma", "0" : "France", "1" : 2644017.71 }
{ "_id" : "BB8Av8GRpPXPsWfzj", "0" : "Denmark", "1" : 2894312.34 }
{ "_id" : "44qbHdtA3wTtf9QFL", "0" : "United Kingdom", "1" : 3391712.21 }
{ "_id" : "YqyWGzXkT4pD532qJ", "0" : "United States", "1" : 9389789.51 }
I've also tried to only find the selected fields ("0" and "1")
SalesData.find({}, {_id:0}).fetch()
Anyone got any tips on how to get the data from a collection in a format that can be used in Highcharts?!
Thanks!
EDIT: I solved it by pushing the required values to an array and set that array as data source.
var seriesData = [];
var reportData = SalesData.find({});
reportData.forEach(function(countryData) {
var dataPoint = [countryData.Country, countryData.Total];
seriesData.push(dataPoint);
console.log(countryData.Country);
});
Actually you can convert the result from a find query directly into an array of values by using cursor.map.
Here is an example for your scenario (using ecmascript2015)
SalesData.find({}, {fields: {Country: 1, Total: 1}}).fetch().map((countryData) =>
{
{return [countryData.Country, countryData.Total]}
})
You should be able to get the data source format needed by highchart
db result is a collection of objects (curly braces on each row). While the static data is an array of values (rectangular braces). So, you need to convert each row in db into array of values.
here is the mapping code:
var ds = [
{ "_id" : "HsgEBrrSvBp6qzp8Q", "0" : "Norway", "1" : 9061000.58 },
{ "_id" : "5dvtddEogj6d5Zw7D", "0" : "Canada", "1" : 1977844.86 },
{ "_id" : "6XmfgjBG4dupes3ma", "0" : "France", "1" : 2644017.71 },
{ "_id" : "BB8Av8GRpPXPsWfzj", "0" : "Denmark", "1" : 2894312.34 },
{ "_id" : "44qbHdtA3wTtf9QFL", "0" : "United Kingdom", "1" : 3391712.21 },
{ "_id" : "YqyWGzXkT4pD532qJ", "0" : "United States", "1" : 9389789.51 }
];
var asValueArray = ds.map(function(row){
return [row["0"],row["1"]];
});
Then, you just assign it to your series object:
series: [{
type: 'pie',
name: 'Sales',
data: asValueArray
}]
Related
I want to remove this
"lightControl" : 75
from this
{
"_id" : "dfdfwef-fdfd-fd94284o-aafg",
"name" : "Testing",
"serialNumber" : "fhidfhd8ghfd",
"description" : "",
"point" : {
"type" : "Point",
"coordinates" : [
10.875447277532754,
20.940549069378634
]
},
"ancestors" : [ ],
"metadata" : {
"measurement" : {
"high" : "40000.0",
"medium" : "25000.0"
},
"digitalTwin" : {
},
"emails" : [
""
],
"lastMeasurementDate" : "2010-03-04T11:32:06.691Z",
"lightControl" : 75
},
"tags" : [ ],
"createdAt" : ISODate("2019-12-07T15:22:10.988Z"),
"updatedAt" : ISODate("2020-03-08T15:38:21.736Z"),
"_class" : "com.test.demo.api.model.Device"
}
All I want is for this specific id, to completely delete the lightControl element from metadata. I have tried $pull, but I am probably missing something. Any ideas? Thank you in advance!
Your lightControl is not in array, for nested property, use the dot wrapped in doublequotes:
MongoDB shell:
db.getCollection('yourCollectionName').update({},{$unset:{
"metadata.lightControl":""
}})
In case you have a list of objects with _id(s) instead of updating directly, assume Node.js client for MongoDB is used:
// import mongodb from "mongodb"; // ES6
const mongodb = require("mongodb");
var client = MongoClient(...);
var coll = client["yourDbName"]["yourCollectionName"];
var objs = []; // <-- The array with _id(s)
for (let i=0; i<objs.length; i++){
let id = mongodb.ObjectID(objs[i]["_id"]);
coll.update({ _id:id },{$unset:{ "metadata.lightControl":"" }});
}
Followup Question
Thanks #4J41 for your spot on resolution. Along the same lines, I'd also like to validate one other thing.
I have a mongo document that contains an array of Strings, and I need to convert this particular array of strings into an array of object containing a key-value pair. Below is my curent appraoch to it.
Mongo Record:
Same mongo record in my initial question below.
Current Query:
templateAttributes.find({platform:"V1"}).map(function(c){
//instantiate a new array
var optionsArray = [];
for (var i=0;i< c['available']['Community']['attributes']['type']['values'].length; i++){
optionsArray[i] = {}; // creates a new object
optionsArray[i].label = c['available']['Community']['attributes']['type']['values'][i];
optionsArray[i].value = c['available']['Community']['attributes']['type']['values'][i];
}
return optionsArray;
})[0];
Result:
[{label:"well-known", value:"well-known"},
{label:"simple", value:"simple"},
{label:"complex", value:"complex"}]
Is my approach efficient enough, or is there a way to optimize the above query to get the same desired result?
Initial Question
I have a mongo document like below:
{
"_id" : ObjectId("57e3720836e36f63695a2ef2"),
"platform" : "A1",
"available" : {
"Community" : {
"attributes" : {
"type" : {
"values" : [
"well-known",
"simple",
"complex"
],
"defaultValue" : "well-known"
},
[......]
}
I'm trying to query the DB and retrieve only the value of defaultValue field.
I tried:
db.templateAttributes.find(
{ platform: "A1" },
{ "available.Community.attributes.type.defaultValue": 1 }
)
as well as
db.templateAttributes.findOne(
{ platform: "A1" },
{ "available.Community.attributes.type.defaultValue": 1 }
)
But they both seem to retrieve the entire object hirarchy like below:
{
"_id" : ObjectId("57e3720836e36f63695a2ef2"),
"available" : {
"Community" : {
"attributes" : {
"type" : {
"defaultValue" : "well-known"
}
}
}
}
}
The only way I could get it to work was with find and map function, but it seems to be convoluted a bit.
Does anyone have a simpler way to get this result?
db.templateAttributes.find(
{ platform: "A1" },
{ "available.Community.attributes.type.defaultValue": 1 }
).map(function(c){
return c['available']['Community']['attributes']['type']['defaultValue']
})[0]
Output
well-known
You could try the following.
Using find:
db.templateAttributes.find({ platform: "A1" }, { "available.Community.attributes.type.defaultValue": 1 }).toArray()[0]['available']['Community']['attributes']['type']['defaultValue']
Using findOne:
db.templateAttributes.findOne({ platform: "A1" }, { "available.Community.attributes.type.defaultValue": 1 })['available']['Community']['attributes']['type']['defaultValue']
Using aggregation:
db.templateAttributes.aggregate([
{"$match":{platform:"A1"}},
{"$project": {_id:0, default:"$available.Community.attributes.type.defaultValue"}}
]).toArray()[0].default
Output:
well-known
Edit: Answering the updated question: Please use aggregation here.
db.templateAttributes.aggregate([
{"$match":{platform:"A1"}}, {"$unwind": "$available.Community.attributes.type.values"},
{$group: {"_id": null, "val":{"$push":{label:"$available.Community.attributes.type.values",
value:"$available.Community.attributes.type.values"}}}}
]).toArray()[0].val
Output:
[
{
"label" : "well-known",
"value" : "well-known"
},
{
"label" : "simple",
"value" : "simple"
},
{
"label" : "complex",
"value" : "complex"
}
]
"translation" : [
{
"language" : "english",
"name" : "shahid Afridi",
"desc" : "batsmen",
"player" : "capten"
},
{
"language" : "spanish",
"name" : "shhid Ofridi",
"desc" : "batsmeen",
"player" : "capteen"
},
{
"language" : "french",
"name" : "hhid afrede is best",
"desc" : "batsmin",
"player" : "captn"
}
],
"auto-publish" : "publish",
"color" : "red",
"boolean" : "true"
I have this document in mongodb
In return
i want translation[0] with auto-publish, color and boolean.
Note: Without using aggregation or putting other sibling's value 1
You can use forEach on your cursor:
db.test.find({}).forEach(function(doc){
if (doc.hasOwnProperty('translation')){
var newdoc = {};
newdoc = doc.translation[0];
newdoc['auto-publish'] = doc['auto-publish'];
newdoc['color'] = doc['color'];
newdoc['boolean'] = doc['boolean'];
print(tojson(newdoc));
}
})
I don't think there's any other way to re-organize document as you need without using aggregation.
I am newbie in MongoDB. I have stored data inside mongoDB in below format
"_id" : ObjectId("51d5725c7be2c20819ac8a22"),
"chrom" : "chr22",
"pos" : 17060409,
"information" : [
{
"name" : "Category",
"value" : "3"
},
{
"name" : "INDEL",
"value" : "INDEL"
},
{
"name" : "DP",
"value" : "31"
},
{
"name" : "FORMAT",
"value" : "GT:PL:GQ"
},
{
"name" : "PV4",
"value" : "1,0.21,0.00096,1"
}
],
"sampleID" : "Job1373964150558382243283"
I want to update the value to 11 which has the name as Category.
I have tried below query:
db.VariantEntries.update({$and:[ { "pos" : 117199533} , { "sampleID" : "Job1373964150558382243283"},{"information.name":"Category"}]},{$set:{'information.value':'11'}})
but Mongo replies
can't append to array using string field name [value]
How one can form a query which will update the particular value?
You can use the $ positional operator to identify the first array element to match the query in the update like this:
db.VariantEntries.update({
"pos": 17060409,
"sampleID": "Job1373964150558382243283",
"information.name":"Category"
},{
$set:{'information.$.value':'11'}
})
In MongoDB you can't adress array values this way. So you should change your schema design to:
"information" : {
'category' : 3,
'INDEL' : INDEL
...
}
Then you can adress the single fields in your query:
db.VariantEntries.update(
{
{"pos" : 117199533} ,
{"sampleID" : "Job1373964150558382243283"},
{"information.category":3}
},
{
$set:{'information.category':'11'}
}
)
I have a 2d index on a coordinates property of my document. Using the mongo shell, I can query the collection like this;
db.adverts.find({coordinates:{$near:[20,40]}})
And that returns the following results, as expected;
{ "_id" : ObjectId("4fddac51352de93903000000"), "title" : "dummy #3", "coordinates" : { "longitude" : 22, "latitude" : 31 } }
{ "_id" : ObjectId("4fddac48352de95105000000"), "title" : "dummy #3", "coordinates" : { "longitude" : 20, "latitude" : 30 } }
{ "_id" : ObjectId("4fddaca4352de93703000000"), "title" : "dummy #3", "coordinates" : { "longitude" : 31, "latitude" : 22 } }
{ "_id" : ObjectId("4fdda6a2352de90a03000000"), "title" : "dummy title", "created" : ISODate("2012-06-17T09:42:58Z"), "coordinates" : { "longitude" : 54.1234, "latitude" : -1.234 } }
{ "_id" : ObjectId("4fdda6d8352de9c004000000"), "title" : "dummy title #2", "created" : ISODate("2012-06-17T09:43:52Z"), "coordinates" : { "longitude" : 54.34, "latitude" : -1.124 } }
However, using Doctrine as per the documentation to query the exact same collection, I get no results e.g.
$adverts = $dm->createQueryBuilder('Advert')
->field('coordinates')->near(20, 40)
->getQuery()
->execute();
$adverts->count(); // => 0
My advert yaml looks like this;
Advert:
type: document
collection: adverts
fields:
id:
id: true
title:
type: string
content:
type: string
created:
type: date
updated:
type: date
status:
type: int
distance:
type: int
indexes:
coordinates:
keys:
coordinates: 2d
referenceOne:
owner:
targetDocument: User
embedOne:
coordinates:
targetDocument: Coordinates
And the Coordinates document is like this;
Coordinates:
type: embeddedDocument
fields:
longitude:
type: float
latitude:
type: float
Any ideas why using Doctrine's ODM would return zero results on the same query?
UPDATE #1
It looks that there is a problem with Doctrine\MongoDB\Query\Builder::near() L363. The method parameter ignores the second value ($y). So only the first value is being passed to be executed.
There appears to be an implementation issue with the near() method (see https://github.com/doctrine/mongodb/pull/53). To fix my original query, I would need to do the following;
$adverts = $dm->createQueryBuilder('Advert')
->field('coordinates.latitude')->near(20)
->field('coordinates.longitude')->near(40);
$adverts->getQuery()->count(); // => 5
This contradicts the current documentation that implies both x, y coordinates can be passed to Doctrine\MongoDB\Query\Builder::near().
EDIT
To make life easier, I've created a custom repository class to provide a more intuitive solution for this inconsistency;
public function near($longitude, $latitude)
{
$query = $this->createQueryBuilder()
->field('coordinates.longitude')->near((float) $longitude)
->field('coordinates.latitude')->near((float) $latitude)
->getQuery();
return $query;
}