Display months in xAxis with Dojo - charts

I have this data :
{ "identifier": "id", "idAttribute":"id", "label": "date",
"items": [
{ "id":1,
"name":"index",
"point":[{"id":1,"num":17, "date":"2009-02-01"},
{"id":2,"num":10, "date":"2009-06-01"}
]},
{ "id":2,
"name":"high",
"point":[{"id":1,"num":11, "date":"2009-01-01"},
{"id":2,"num":19, "date":"2009-09-01"}
]},
{ "id":3,
"name":"low",
"point":[{"id":1,"num":14, "date":"2009-07-01"},
{"id":2,"num":20, "date":"2009-03-01"}
]}
]}
I want to display it in this chart.
Also, I don’t know how can I put the month’s date in the labels.
dojo.require(”dojox.charting.DataChart”);
dojo.require(”dojo.data.ItemFileWriteStore”);
dojo.addOnLoad(function() {
dojo.require("dojox.charting.DataChart");
dojo.require("dojo.data.ItemFileWriteStore");
dojo.addOnLoad(function() {
var store = new dojo.data.ItemFileWriteStore({
url: "exemple_stock.json"
});
chart = new dojox.charting.DataChart("chartDiv" ,{ displayRange:12,
xaxis:{labels:["0", "Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"]},
yaxis:{max:100,min:0, majorTickStep:10, maxLabelSize:30},
type: dojox.charting.plot2d.Lines
});
chart.setStore(store, {symbol:"*"}, "point"); // <-- single value property
});

I don't know how to do it with DataChart, but regular Dojo charts can do any kind of labels without problems: http://archive.dojotoolkit.org/nightly/dojotoolkit/dojox/charting/tests/test_labels2d.html
If you need to use a dojo.data store as your data source, consider using DataSeries with regular charts:
http://docs.dojocampus.org/dojox/charting#using-dojo-data-data-sources-with-charts
http://dojotoolkit.org/api/dojox/charting/DataSeries.html
http://archive.dojotoolkit.org/nightly/dojotoolkit/dojox/charting/tests/test_DataSeries.html

Related

Isn't it possible to concat new value to a field in MongoDB document while updating it?

I have few documents in a MongoDB Collection and each has a unique field called "requestid". Now I need to update a field "requeststatus" by concatenating a new value to an existing one in NodeJS application. I started using MongoDB for very recent and have less exposure in it's features.
After doing some research I got to know I could use "$set" with "$concat"
Updating with filter & options:
var filter = { requestid: data.requestid };
var updateDoc = { $set: { requeststatus: { $concat: ["$requeststatus","-",`. ${data.status}`] } } };
var options = { multi: true };
var jobDetails = { filter, updateDoc, options };
NodeJS code:
async function updateJobDetails(connection, data, mongoDetails){
const result = await connection.db(mongoDetails.mongoDatabase).collection(mongoDetails.collection).updateOne(data.filter, data.updateDoc, data.options);
}
This is not doing as expected, instead it's adding the new concatenated value as array of Object into MongoDB collection.
Existing document:
{
"_id": {
"$oid": "6307120d3oiu895oi9e82eea5"
},
"requestid": "123456789",
"iscancelled": true,
"organizationid": "3",
"instanceid": "172",
"offerid": "offer123",
"promotionid": "promo123",
"jobtype": "portaljob123",
"jobid": "job123",
"requeststatus": "began"
}
Updated document:
{
"_id": {
"$oid": "6307120d3oiu895oi9e82eea5"
},
"requestid": "123456789",
"iscancelled": true,
"organizationid": "3",
"instanceid": "172",
"offerid": "offer123",
"promotionid": "promo123",
"jobtype": "portaljob123",
"jobid": "job123",
"requeststatus": {
"$concat": ["$requeststatus", "-", "tigger_datalink stopped since request was cancelled"]
}
}
Is there anything that I am doing wrong here? I even tried updateMany() but of no use. Run it as many times as desired it won't concat but keep updating same value as Object Any help is appreciated here.
(Working) Updated NodeJS code:
async function updateJobDetails(connection, data, mongoDetails){
const result = await connection.db(mongoDetails.mongoDatabase).collection(mongoDetails.collection).updateOne(data.filter, [data.updateDoc], data.options);
}
In order to use an existing field's data you need to use an update with a pipeline.
Try using your updateDoc inside a pipeline, like this:
var filter = { requestid: data.requestid };
var updateDoc = { $set: { requeststatus: { $concat: ["$requeststatus","-",`. ${data.status}`] } } };
var options = { multi: true };
var jobDetails = { filter, [updateDoc], options };
See how it works on the playground example

MongoDB/Mongoose How to add elements in a complex structure

I've this complex structure in a project I'm working on, and I can't find a way to bulk add some values in the "parametri" array.
Here is an example document:
My goal is to add some values to "parametri" array that is inside the Object at position 1 of the array "protocolli".
In mongoDB Compass I can do a select using "'protocolli.nome': 'protocollo-2'", so I've tried the following code (the project is written in TS, uses a NestJs backend and Mongoose to communicate with MongoDB):
this.model.updateMany(
{ 'protocolli.nome': ProtocolloAlert.PROTOCOLLO_2 },
{
$push: {
'protocolli.parametri': {
$each: [
TipoParametro.FAT_MASS,
TipoParametro.DISTANCE,
TipoParametro.MUSCLE_MASS,
TipoParametro.STEPS,
TipoParametro.CALORIES,
TipoParametro.MINUTES,
],
},
},
},
{ multi: true }
)
I've already tried $push, $addToSet, $set with no positive result..
Using this method, I've the following error:
MongoError: Cannot create field 'parametri' in element {protocolli: [ { nome: "protocollo-1", parametri: [ "temp", "spo2", "hr", "sys" ], descrizione: "Attivazione alert in control room, inserimento nei log degli alert in corso, salvataggio nella scheda alert del paziente" }, { nome: "protocollo-2", parametri: [ "dya", "pulse", "fr", "pef", "fev1", "fvc", "fev1fvc", "etco2", "freqRes", "glucose", "weight", "height", "bmi", "bodyFat", "hba1c", "totCh", "triglycerides", "hdl", "ldl" ], descrizione: "Salvataggio nella scheda alert del paziente" } ]}
at Function.create (C:....\node_modules\mongodb\lib\core\error.js:57:12)
Thanks in advance.

Put properties with different name in one field in MongoDB

I am getting requests from different devices as Json. Some of them show temperature as "T", some other as "temp" and it can be different in other devices. is that possible to define in MongoDB to put all of these values in single field "temperature"?
Doesn't matter if it is "temp" or "T" or "tempC", just put all of them in "temperature" field.
Here is an example of my data:
[
{ "ip": "12:3B:6A:1A:E6:8B", "type": 0, "t": 37},
{ "ip": "22:33:66:1A:E6:8B", "type": 1, "temperature": 40},
{ "ip": "1A:3C:6A:1A:E6:8B", "type": 1, "temp": 30}
]
I want to put temp, t and temperature in Temperature field in my collection.
You can use $ifNull operator to control which value should be transferred into your output, like below:
db.col.aggregate([
{
$addFields: { Temperature: { $ifNull: [ { $ifNull: [ "$t", "$temperature"] }, "$temp" ] } }
},
{
$project: {
t: 0,
temperature: 0,
temp: 0
}
}
])
This will merge that three fields into one Temperature taking first not empty value. Additionally if you want to update your collection, you can add $out as a last aggregation stage like { $out: col } but keep in mind that it will entirely replace your source collection.
I think mongodb supports regular expression but they are meant to search datas, not to insert them based on fieldname matches.
I am quite sure you shall use some kind of facade in front of your database to achieve that.

How to replace prefetch source in Bloodhound with a 'real time' alternative?

I've been using Bloodhound with the prefetch [docs] option defined.
This works fine, except when I add content to the json file being prefetched, it is not available as a search result unless I restart the browser.
So I am trying to make the search results reflect the updated file content in 'real time'.
I tried simply replacing prefetch with remote but this causes the search functionality not to work as intended (it shows non-matched results).
Below is the code I am using with prefetch.
Version info: typeahead.bundle.min.js at v0.10.5.
function searchFunction() {
var template =
"<p class=\"class_one\">{{area}}</p><p class=\"class_two\">{{title}}</p><p class=\"class_three\">{{description}}</p>";
var compiled_template = Hogan.compile(template);
var dataSource = new Bloodhound({
datumTokenizer: function(d) {
return Bloodhound.tokenizers.whitespace(d.tokens.join(
' '));
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
prefetch: '/static/my_file.json'
# remote: '/search'
});
dataSource.initialize();
$('.my_lookup .typeahead').typeahead({}, {
source: dataSource.ttAdapter(),
name: 'courses',
displayKey: 'title',
templates: {
suggestion: compiled_template.render.bind(
compiled_template)
}
}).focus().on('typeahead:selected', function(event, selection) {
var title = selection.title
// do things with the title variable
});
}
Edit:
I started thinking perhaps I need some server side logic to perform a search on a database that contains the content previously within the local json file.
Using the code posted below, the following works:
Searches database in real time.
All matches are returned.
The following does not work:
It does not offer suggestions, you have to type the full token name.
If searching for apple, it will search after typing a, then p etc, if it doesn't get any results, it shows this error in Firebug: TypeError: data is null. After a few of these errors, it stops triggering searches and no error is displayed.
And, the results from the database are in the following format, and I don't know how to apply the Hogan template for the suggestions to each result:
{
"matches": [{
"tokens": ["apple", "orange"],
"area": "Nautical",
"_id": {
"$oid": "4793765242f9d1337be3d538"
},
"title": "Boats",
"description": "Here is a description"
}, {
"tokens": ["apple", "pineapple"],
"area": "Aviation",
"_id": {
"$oid": "4793765242f9d1337be3d539"
},
"title": "Planes",
"description": "Here is a description."
}]
}
JS
function searchFunction() {
var engine = new Bloodhound({
remote: {
url: '/search?q=%QUERY%',
wildcard: '%QUERY%'
},
datumTokenizer: Bloodhound.tokenizers.whitespace('q'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
});
engine.initialize();
$('.my_lookup .typeahead').typeahead({
}, {
source: engine.ttAdapter(),
name: 'courses',
displayKey: 'title',
templates: {
suggestion: function (data) {
return "// not sure how to apply markup to each match"
}
}
}).focus().on('typeahead:selected', function(event, selection) {
console.log(selection);
var title = "// again not sure how to access individual match data"
// do things with the title variable
});
}
MongoDB Schema
Database: courses
Collection: courses
Documents:
{
"_id" : ObjectId("4793765242f9d1337be3d538"),
"tokens" : [
"apple",
"orange"
],
"area" : "Nautical",
"title" : "Boats",
"description" : "Here is a description."
}
and:
{
"_id" : ObjectId("4793765242f9d1337be3d539"),
"tokens" : [
"apple",
"pineapple"
],
"area" : "Aviation",
"title" : "Planes",
"description" : "Here is a description."
}
etc
Python (using Bottle routes)
#route('/search')
def search():
"""
Query courses database for matches in tokens field.
"""
# get the query
query = request.GET.q
# define the database
dbname = 'courses'
db = connection[dbname]
# define the collection
collection = db.courses
# make the query
matches = collection.find({"tokens":query})
# send back results
results = {}
results['matches'] = matches
response.content_type = 'application/json'
return dumps(results)

Meteor. Sorting my collection by a deeply nested value

In my application I have a list of tiles representing each project in a portfolio. This is the main list view for the app and all projects are fetched from the collection without any sorting or ordering.
When I have an optional slug parameter specified in my route (for the category assigned to the project) I want to be able to display the projects within the UI that match that category first, and then display the other ones that don't match the category.
For reference, I have included the code for the route below:
/**
* Project list view (all projects) with optional
* filter parameter for showing projects only by
* their category name.
*/
this.route('list', {
path: '/:_category_slug?',
template: 'template_main',
action: function() {
if(this.ready()) {
this.render();
}
},
waitOn: function() {
return [
Meteor.subscribe('projects'),
Meteor.subscribe('formations'),
Meteor.subscribe('categories')
];
},
data: function() {
if(this.params._category_slug) {
/**
* Building up the query given the category slug and the language
*/
var query = {};
query['slug.' + App.language] = this.params._category_slug;
/**
* Grab the category given the query, so we can get its 'id'
*/
var category = App.models.categories.findOne(query);
/**
* This is the query I need to work on so that I can achieve what I want
*/
return App.models.projects.find({}).fetch();
}
else {
return App.models.projects.find({}).fetch();
}
},
yieldTemplates: {
'components_header': {to: 'header'},
'views_list': {to: 'content'},
'components_footer': {to: 'footer'}
}
});
For reference, I have also included a sample of the data for three projects that is relevant to this question.
{
"id": 10,
"slug": {
"en": "sample-english-slug",
},
"title": {
"en": "Sample English Title",
},
"description": {
"en": "A good description.",
},
"category_ids": [
{
"id": 5
},
{
"id": 6
}
],
},
{
"id": 12,
"slug": {
"en": "another-sample-slug",
},
"title": {
"en": "Another sample title",
},
"description": {
"en": "Sample description three",
},
"category_ids": [
{
"id": 1
},
{
"id": 4
}
],
},
{
"id": 11,
"slug": {
"en": "another-sample-slug",
},
"title": {
"en": "A sample title",
},
"description": {
"en": "Sample description",
},
"category_ids": [
{
"id": 2
},
{
"id": 5
}
],
}
So what I would want to do is make sure that given a category with an ID of 5, I want those first two projects to be the first two that appear.
Can this be done in meteor, without having to resort to writing extra logic in JS? One approach I did have once was to update each project from within the Client side collection (something I no longer do) and set a few extra attributes, then sort after that.
When dealing with syncing client and server collections, this is not really feasible.
From the mongodb docs:
Use the dot notation to match by specific fields in an embedded document. Equality matches for specific fields in an embedded document will select documents in the collection where the embedded document contains the specified fields with the specified values. The embedded document can contain additional fields.
I don't know if you can do it with a single query, but you can concat two complementary queries that use dot notation.
var selected = App.models.projects.find({'category_ids.id': category._id}).fetch();
var other = App.models.projects.find({'category_ids.id': {$ne: category._id}}).fetch();
return selected.concat(other);