How to get MongoDB all indexes usage and size - javascript

I am trying to get MongoDB indexes usage and size in the same output.
db.getCollection(collection).stats().indexSizes; gives sizes
and db.getCollection(collection).aggregate({ "$indexStats": {} }); gives just usage.
Is there a command to output both?

Both queries can be combined on intellishell, since it uses syntax similar to javascript we can run the following script.
db = db.getSiblingDB("your-db-name");
const collections = db.getCollectionNames();
const result = [];
for (const collection of collections) {
const sizes = db.getCollection(collection).stats().indexSizes;
const indexStats = db.getCollection(collection).aggregate({ "$indexStats": {} }).toArray();
for (const index of indexStats) {
index.collection = collection;
index.size = sizes[index.name];
result.push(index)
}
}
print (result)
notice the conversion to .toArray() in order to loop easily over it.

Related

mongodb find method to display all data if array is empty

Let say I have dynamic array
const branddata = ["adidas", "nike", "puma"]
//this data can be sometime empty too like
// const branddata = []
//now I want to search all the product with brands like
const product = productmodel.find({brand:branddata})
The problem is, this thing works when branddata array is not empty and it gives me the product.
But when it is empty the find method search for a brand which is equal to "" and gives me zero product.
I want all the products to be displayed if branddata is empty.
How can I get this using $regex or any other?
you can check branddata is empty or not, and create query object based on it, like this
let q=(branddata && branddata.length>0 )?{brand:branddata}:{};
const product = productmodel.find(q);
when you have multiple params,you can do something like this
let params={
"brand":branddata,
"price":pricedata,
"gender":genderdata
}
let q={};
Object.Keys(params).forEach((t)=>{
if(params[t] && params[t].length>0 ){
q[t]=params[t]
}
})
const product = productmodel.find(q);
Finally found a solution with a function-based approach
$in is used to find document data which are in the array and $nin is used to find document data which are not in the array (basically when array is empty)
const branddata = ["adidas", "nike", "puma"]
const pricedata =["100"]
const genderdata =["male","female"]
const queryfunc = (value)=>{
var q = {}
if(value==''){
q["$nin"]=value;
}
else{
q["$in"]=key;
}
return q
}
const brand=queryfunc(branddata)
const price=queryfunc(pricedata)
const gender=queryfunc(genderdata)
const product = productmodel.find({brand,price,gender})

Add JSON values from two different files into a single file

I just need to merge two files with the same list, but with different values on each file. Preferably in JavaScript
For example:
File 1
{"list1":{"a":1,"b":2}
{"list2":{"c":3,"d":4}
File 2
{"list1":{"a":5,"b":6}
{"list2":{"c":7,"d":8}
The desired result is
{"list1":{"a":6,"b":8}
{"list2":{"c":10,"d":12}
Sorry for the noob question, but the person who sent me the files should have done this themselves, but are currently unavailable. The files are too big to do by hand.
This is not very flexible code, but it would be far more work, to make something more dynamic. You would have to parse the objects recursevely and check if the property is an object and then jump deeper. Until ou find the values.
And please be aware that I'm not making any type checking whatsoever. If the data contains faulty data it is not cought properly. Also this code requires this exact structure. If your object contains other properties it might crash too.
// your data
const f1l1 = '{"list1":{"a":1,"b":2}}';
const f1l2 = '{"list2":{"c":3,"d":4}}';
const f2l1 = '{"list1":{"a":5,"b":6}}';
const f2l2 = '{"list2":{"c":7,"d":8}}';
var result1= JSON.parse(f1l1);
var result2= JSON.parse(f1l2);
//the names of the list as they appear in your real data *must* be the first object
const nameList1 = Object.keys(result1)[0];
const nameList2 = Object.keys(result2)[0];
//remove the list name
result1=result1[nameList1];
result2= result2[nameList2];
//get data from other file nd remove list name
const file2List1= JSON.parse(f2l1)[nameList1];
const file2List2= JSON.parse(f2l2)[nameList2];
// go through all items and sum them if the value is already in the list, else put it in for list1
for (var prop in file2List1) {
if (Object.prototype.hasOwnProperty.call(file2List1, prop)) {
if(Object.prototype.hasOwnProperty.call(result1, prop)){
result1[prop] = result1[prop] + file2List1[prop];
}else{
result1[prop] = file2List1[prop];
}
}
}
// and now for list2
for (var prop in file2List2) {
if (Object.prototype.hasOwnProperty.call(file2List2, prop)) {
if(Object.prototype.hasOwnProperty.call(result2, prop)){
result2[prop] = result2[prop] + file2List2[prop];
}else{
result2[prop] = file2List2[prop];
}
}
}
//put names of lists back in.
result1 = {[nameList1]:result1};
result2 = {[nameList2]:result2};
//check results:
console.log("input data:");
console.log(JSON.parse(f1l1));
console.log(JSON.parse(f1l2));
console.log(JSON.parse(f2l1));
console.log(JSON.parse(f2l2));
console.log("output data:");
console.log(result1);
console.log(result2);
You can try this out
newList = list1.concat(list2);

Large json, store two fields in an array

I have a large json file that needs to have to "fields" merged in to an array in order to store to firestore.
Here a screenshot to show what I mean. What i have:
What I need:
As you can see GRP1D and GRP2D where merged in to an array. The json has 15000 entries so doing it manually is not an option
You can write a script using NodeJS to edit this huge file similar to the following:
const largeJson = require('./largeJson.json');
// I am assuming here that the large JSON file is an array of objects
const mergedJson = largeJson.map(obj => {
const objEditted = { ...obj, GRP1D: [ obj.GRP1D, obj.GRP2D ] };
delete objEditted.GRP2D;
return objEditted;
});
// mergedJson now holds an array of objects which merge the fields
// GRP1D and GRP2D as you described in the example
Here is small code snippet using the spread operator
const your_data = require("./your_data/ file/path");
const prepare_func = (your_data)=>{
let temp = {...your_data,"GRP1D":[your_data["GRP1D"],your_data["GRP2D"]]};
return temp;
}
let new_data = prepare_func(your_data);

How to convert mysql row of data into a javascript array? Node.js app

First, I'm a newbie. No doubt, I've made some simple errors.
Using Node.js with MySQL Database, I'm building a basic web app that allows users to login. Once they've logged in they will be brought to their profile page and are displayed results of a quiz they've done in the form of a bar chart.
I want covert a row of mysql data into an array.
const mysql = require('mysql');
const dbconfig = require('/config/database');
const connection = mysql.createConnection(dbconfig.connection);
connection.query('USE ' + dbconfig.database);
// Create an array of scores for each category depedning on the user who's
// loggedin.
var category1scoreQuery =
"SELECT c1q1, c1q2, c1q3, c1q4, c1q5, c1q6, c1q7, c1q8
FROM nodejs_login.assessment_score
AS a JOIN users as u ON a.respondent_id = u.user_respondent_id
WHERE a.respondent_id = user.user_respondent_id;";
connection.connect(function(err){
if (err) throw err;
connection.query(category1scoreQuery, function(err, result, fields) {
if (err) throw err;
Object.keys(result).forEach(function(key){
var cat1Array = result[key];
// want to return array e.g. ["45/60", "60/60", "40/40","30/40","15/20",
// "30/40", "30/60", "20/40"];
console.log(cat1Array);
})
})
});
// I want to convert it to an array to parse the array of strings into
// totalUserScore over maxCategoryScore
var i;
var userCategoryScore1 = 0;
var maxCategoryScore = 0;
for(i=0; i < cat1Array.length;i++){
var splitScore = cat1Array[i].split("/");
console.log(splitScore);
myQuestionScore = parseInt(splitScore[0], 10);
userCategoryScore1 += myQuestionScore;
console.log(userCategoryScore);
maxQuestionScore = parseInt(splitScore[1]);
maxCategoryScore = maxCategoryScore + maxQuestionScore;
console.log(maxCategoryScore);
}
This is what I am actually getting which doesn't allow me to loop through.
RowDataPacket {
c1q1: '15/60',
c1q2: '15/60',
c1q3: '10/40',
c1q4: '10/40',
c1q5: '5/20',
c1q6: '10/40',
c1q7: '15/60',
c1q8: '10/40' }
This should work for you:
const RowDataPacket= {
c1q1: '15/60',
c1q2: '15/60',
c1q3: '10/40',
c1q4: '10/40',
c1q5: '5/20',
c1q6: '10/40',
c1q7: '15/60',
c1q8: '10/40' }
const values=Object.values(RowDataPacket);
console.log(values)
Reference[1st part] : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Object/values
Description:
The Object.values() method returns an array of a given object's own enumerable property values, in the same order as that provided by a for...in loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).
For the second part, to calculate the total scores:
//using the values array from first part
const scores=values.reduce((accum,value)=>{
const splitValues=value.split('/')
return {
score:accum.score + parseInt(splitValues[0]),
maxScore:accum.maxScore + parseInt(splitValues[1]),
}
},{score:0,maxScore:0})
console.log(scores)
Reference[2nd part]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
Description:
The reduce() method executes a reducer function (that you provide) on each element of the array, resulting in a single output value.
This is fairly common problem when interacting with a database through javascript. To get what you want you can try using JSON library like this:
usersRows = JSON.parse(JSON.stringify(result));
Also this isn't exactly related to your question but it's something that made my life a lot easier when I was doing this: consider using the node Promisify module to transform your queries into promises (from here: https://www.npmjs.com/package/util-promisify). That way instead of having to use callbacks like you are doing your code would look something like this:
var results = await connection.query(category1scoreQuery);
//Process results here
Again this is only a suggestion but something that I found was very useful.
Cheers!

What is the best way to realise "join" with JS objects?

I'm working with MeteorJS (aned MongoDB).
I have two collections :
events, with idEvent
eventsType, with idEventType (finite list of
type of events)
The link between two collections must be realized with idEvent == idEventType.
The goal is to have an array of events, with eventstype object associed.
This following code is functionnal, but I find it horrible... What did you think about ?
events() {
// Type of event
const eventsType = EventsType.find();
const eventsTypeArray = [];
eventsType.forEach((ev) => {
eventsTypeArray[ev.idEventType] = ev;
});
// List of events
const eventsList = Events.find();
const eventsListArray = [];
// Merge both data
eventsList.forEach((ev) => {
const evObj = ev;
evObj.type = eventsTypeArray[ev.idEvent];
eventsListArray.push(evObj);
});
return eventsListArray;
}
Thanks ! :D
You could map your eventsList and use Object.assign to enrich the original item :
eventsListArray = eventsList.map(ev => Object.assign({type: eventsTypeArray[ev.idEvent]}, ev))
Test run :
originalArray = [{a:"1"}, {a:"2"}];
dataMap = { "1": 10, "2": 100 };
mappedArray = originalArray.map(i=>Object.assign({b:dataMap[i.a]}, i));
console.log(originalArray);
console.log(mappedArray);
Result :
[{a:"1"}, {a:"2"}] //original array left untouched
[{a:"1", b:10}, {a:"2", b:100}] // mappedArray contains the extra data
I actually had a similar problem recently where I wanted to join data from two collections.
My solution was to create a new local collection (this is a collection that lives on the client only).
client:
const LocalEvents = new Mongo.Collection(null);
From there, instead of pushing your joined objects in to an array, you can join them and push the new objects in to the LocalEvents collection. This gives you the benefit of being able to query the new objects from the local minimongo collection. You'll need to make sure you clear the local collection when the template/component is destroyed. Also run a tracker function to empty the LocalCollection if your cursor changes.
Tracker.autorun((eventsType) => {
LocalEvents.remove({});
});

Categories