How to extract values of Sequelize criteria? - json

Lets say I have table student
Student
id first_name last_name
1 Adam First
2 Adam Second
I have Javascript function that creates a criteria based on parameters it gets.
function createCriteria(lastName, id) {
// if either last name or id only are present then return
// criteria of that one parameter.
// For example.
// if only lastName is present return criteria {'lastName': 'First'}
// if only id is present return criteria {[Op.in]: {'id': [1, 2]}}
// If both are present, then consider both and return
// {[Op.and]: [{'lastName': 'First'}, {[Op.in]: {'id': [1, 2]}}]}
}
function runQuery() {
const criteria = createCriteria('First', [1, 2]);
// run the sequelize query
}
So far all is fine. The problem I am having is unit testing the createCriteria function.
Specifically, testing nested cases like this one.
{[Op.and]: [{'lastName': 'First'}, {[Op.in]: {'id': [1, 2]}}]}
Jest can test using the method toHaveProperty. So you can write,
expect(criteria).toHaveProperty([Op.and]);
But, this only works for the first level.
How, would you fetch this value. [{'lastName': 'First'}, {[Op.in]: {'id': [1, 2]}}] which is indexed by key [Op.and].
I might be missing how JSON or Javascript works, but criteria[[Op.and]] or criteria.[Op.and] or criteria['[Op.and]'] does not work.
Sequelize Op are symbols so if you use inspect it will show up something like
{[Symbol(and)]: [{'lastName': 'First'}, {[Symbol(in)]: {'id': [1, 2]}}]}
Does anyone know how to extract values out of JSON, which is a Sequelize criteria, as the keys are Sequelize operators, and not exactly strings or literals.

Related

How to get another key value from an array of json?

Lets say I have these arrayed JSON values
[{operation_id: 2, operation_name: FAITHFUL BELIEVERS},
{operation_id: 3, operation_name: SAMPLE OP},
{operation_id: 4, operation_name: SAMPLE OP 2}]
Now I will select the operation name 'SAMPLE OP' but I want to display the value of its operation_id. How would I do that?
Your JSON is a list of maps, so use where on the list to filter it by your predicate. Better still, use firstWhere as we assume there's just one match.
The match function returns true if the operation name member of the map matches.
firstWhere returns the first matching map, and you want the operation id member of that map.
final id = list
.firstWhere((m) => m['operation_name'] == 'SAMPLE OP')['operation_id'];

Store contract results tag in a variable

I have a web3 contstant look like this.
const test = contract_instance.methods.getPost(15).call().then(console.log);
This returns results like this.
Result {
'0': '2017-08-28',
'1': '19:18:04.986593',
'2': '07:17:00',
'3': '11112323',
'4': '12',
date: '2017-08-28',
login_time: '19:18:04.986593',
logout_time: '07:17:00',
login_device_id: '11112323',
user_id: '12' }
Now when i want to console single tag through console.log(test[0]); this returns undefined
My approach is to store every result tag in its individual variable. Need some suggestion.
then() takes a function as argument that is called on fulfillment of the promise. You can then add the value to an array for example:
var results = []
contract_instance.methods.getPost(15).call().then(function(value){
console.log(value)
results.push(value)
});
results[0] would then be the result object you are looking for and results[0]['0'] would give you the date '2017-08-28' for example.
By chaining the calls with .then(...), the returned value is of type Promise and not the Result object that you are expecting (and what's written to the console) and cannot be accessed by index.
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then for more information.

Laravel - Group By & Key By together

Assuming I have the following MySQL tables to represent pricebooks, items and the relationship between them:
item - item_id|name|...etc
pricebook - pricebook_id|name|...etc
and the following pivot table
pricebook_item - pricebook_id|item_id|price|...etc
I have the correlating Eloquent models: Pricebook, Item and a repository named PricebookData to retrieve the necessary information.
Within the PricebookData repository, I need to get the pricebook data grouped by pricebook id and then keyed by item_id for easy access on client side.
If I do:
Pricebook::all()->groupBy('pricebook_id');
I get the information grouped by the pricebook_id but inside each pricebook the keys are simple numeric index (it arrives as js array) and not the actual product_id. So when returning to client side Javascript, the result arrives as the following:
pricebookData: {1: [{}, {}, {}...], 2: [{}, {}, {}...]}
The problem with the prices arriving as array, is that I can not access it easily without iterating the array. Ideally I would be able to receive it as:
pricebookData: {1: {1001:{}, 1002: {}, 1003: {}}, 2: {1001:{}, 1002: {}, 1003: {}}}
//where 1001, 1002, 1003 are actual item ids
//with this result format, I could simply do var price = pricebookData[1][1001]
I've also tried the following but without success:
Pricebook::all()->keyBy('item_id')->groupBy('pricebook_id');
The equivalent of what I am trying to avoid is:
$prices = Pricebook::all();
$priceData = [];
foreach ($prices as $price)
{
if (!isset($priceData[$price->pricebook_id]))
{
$priceData[$price->pricebook_id] = [];
}
$priceData[$price->pricebook_id][$price->item_id] = $price;
}
return $priceData;
I am trying to find a pure elegant Eloquent/Query Builder solution.
I think what you want is
Pricebook::all()
->groupBy('pricebook_id')
->map(function ($pb) { return $pb->keyBy('item_id'); });
You first group by Pricebook, then each Pricebook subset is keyed by item_id. You were on the right track with
Pricebook::all()->keyBy('item_id')->groupBy('pricebook_id');
unfortunately, as it is implemented, the groupBy resets previous keys.
Update:
Pricebook::all()->keyBy('item_id')->groupBy('pricebook_id', true);
(groupBy second parameter $preserveKeys)

Sorting users in Rails based on values in array attribute of user model

I have a User model which has an array inside of it. This array is used to store points the user has scored in various activities. It basically looks like this:
<ActiveRecord::Relation [#<User id: 1, fullname: "Kaja Sunniva Edvardsen", points: [0, 4170, 3860, 2504, 2971, 3859, 4346]>, #<User id: 2, fullname: "Alexander Lie Sr.", points: [0, 3273, 3681, 2297, 2748, 4202, 3477]>]>
I want to sort all Users by the different values in the points array to be able to create ranking list for each of the different activities, points[0], points[1], etc...
Sorting by points[1] should return Kaja first, 4170>3273, sorting by points[6] should put Alexander first, 4202>3859
How do I do this?
As far as I know, MySQL does not have an integrated array type.
Assuming you have a model like this:
class User < ActiveRecord::Base
# ...
serialize :points, Array
# ...
end
You cannot sort with order queries, but you can try another solution (less efficient), handling the resources as an array:
User.all.sort { |user1, user2| user2.points[1] <=> user1.points[1] }
Which will return an array instead of an ActiveRecord query. Also, bear in mind that this code will not handle nil values (i.e. What if an user only have 2 elements in points?).

CSV Parser through angularJS

I am building a CSV file parser through node and Angular . so basically a user upload a csv file , on my server side which is node the csv file is traversed and parsed using node-csv
. This works fine and it returns me an array of object based on csv file given as input , Now on angular end I need to display two table one is csv file data itself and another is cross tabulation analysis. I am facing problem while rendering data, so for a table like
I am getting parse responce as
For cross tabulation we need data in a tabular form as
I have a object array which I need to manipulate in best possible way so as to make easily render on html page . I am not getting a way how to do calculation on data I get so as to store cross tabulation result .Any idea on how should I approach .
data json is :
[{"Sample #":"1","Gender":"Female","Handedness;":"Right-handed;"},{"Sample #":"2","Gender":"Male","Handedness;":"Left-handed;"},{"Sample #":"3","Gender":"Female","Handedness;":"Right-handed;"},{"Sample #":"4","Gender":"Male","Handedness;":"Right-handed;"},{"Sample #":"5","Gender":"Male","Handedness;":"Left-handed;"},{"Sample #":"6","Gender":"Male","Handedness;":"Right-handed;"},{"Sample #":"7","Gender":"Female","Handedness;":"Right-handed;"},{"Sample #":"8","Gender":"Female","Handedness;":"Left-handed;"},{"Sample #":"9","Gender":"Male","Handedness;":"Right-handed;"},{"Sample #":";"}
There are many ways you can do this and since you have not been very specific on the usage, I will go with the simplest one.
Assuming you have an object structure such as this:
[
{gender: 'female', handdness: 'lefthanded', id: 1},
{gender: 'male', handdness: 'lefthanded', id: 2},
{gender: 'female', handdness: 'righthanded', id: 3},
{gender: 'female', handdness: 'lefthanded', id: 4},
{gender: 'female', handdness: 'righthanded', id: 5}
]
and in your controller you have exposed this with something like:
$scope.members = [the above array of objects];
and you want to display the total of female members of this object, you could filter this in your html
{{(members | filter:{gender:'female'}).length}}
Now, if you are going to make this a table it will obviously make some ugly and unreadable html so especially if you are going to repeat using this, it would be a good case for making a directive and repeat it anywhere, with the prerequisite of providing a scope object named tabData (or whatever you wish) in your parent scope
.directive('tabbed', function () {
return {
restrict: 'E',
template: '<table><tr><td>{{(tabData | filter:{gender:"female"}).length}}</td></tr><td>{{(tabData | filter:{handedness:"lefthanded"}).length}}</td></table>'
}
});
You would use this in your html like so:
<tabbed></tabbed>
And there are ofcourse many ways to improve this as you wish.
This is more of a general data structure/JS question than Angular related.
Functional helpers from Lo-dash come in very handy here:
_(data) // Create a chainable object from the data to execute functions with
.groupBy('Gender') // Group the data by its `Gender` attribute
// map these groups, using `mapValues` so the named `Gender` keys persist
.mapValues(function(gender) {
// Create named count objects for all handednesses
var counts = _.countBy(gender, 'Handedness');
// Calculate the total of all handednesses by summing
// all the values of this named object
counts.Total = _(counts)
.values()
.reduce(function(sum, num) { return sum + num });
// Return this named count object -- this is what each gender will map to
return counts;
}).value(); // get the value of the chain
No need to worry about for-loops or anything of the sort, and this code also works without any changes for more than two genders (even for more than two handednesses - think of the aliens and the ambidextrous). If you aren't sure exactly what's happening, it should be easy enough to pick apart the single steps and their result values of this code example.
Calculating the total row for all genders will work in a similar manner.