Can an array be used as a d3 nest key? - d3.js

I have a database of movies that I would like to nest by genre. The problem is that each movie can have multiple genres. So if I have several movies formatted like so
[
{
title : 'foo',
genres : ['Action', 'Comedy', 'Thriller']
},{
title : 'bar',
genres : ['Action']
}
]
I'd like to nest them by each individual genre so that the result would be
[
{
key: 'Action',
values: [ { title: 'foo' }, { title: 'bar'} ]
},{
key: 'Comedy',
values: [ { title: 'foo' } ]
},{
key: 'Thriller',
values: [ { title: 'foo' } ]
}
]

not directly, but you can expand your array
For example:
jj = [{ genre: ['thriller', 'comedy'], title: 'foo'}, { genre: ['thriller', 'action'], title: 'papa'}]
to expand your array:
jj2 = []
jj.forEach(function(movie) { movie.genre.forEach( function(single_genre) { jj2.push({ language: movie.language, genre: single_genre, title: movie.title } ); } ); })
Then you can perform your nesting as normal:
d3.nest().key(function(d) { return d.genre; }).entries(jj2)

Related

Vuelidate: Conditionally adding validation models

I recently made the switch with Vuelidate from Vee-Validate a few weeks ago for all our apps and have been loving its flexibility so far; however, I've run across an issue that I'm not quite sure how to solve...
I've added the (primitive) example, using my real data here:
https://jsfiddle.net/80cuuagp/18/
From the fiddle:
new Vue({
el: "#app",
data() {
return {
questions: [
{
message: '1. Do you expect to conduct cash transactions for this account? ',
value: false,
conditionalFields: [
{
title: 'Cash In',
fields: [
{ label: 'Total Amount', value: '' },
{ label: 'Frequency', value: '' }
]
},
{
title: 'Cash Out',
fields: [
{ label: 'Total Amount', value: '' },
{ label: 'Frequency', value: '' }
]
}
]
},
{
message: '2. Will Electronic (ACH) transactions be processed on the account (excluding card transactions)?',
value: false,
conditionalFields: [
{
title: 'Electronic Deposits',
fields: [
{ label: 'Total Amount', value: '' },
{ label: 'Frequency', value: '' }
]
},
{
title: 'Electronic Withdrawals',
fields: [
{ label: 'Total Amount', value: '' },
{ label: 'Frequency', value: '' }
]
}
]
},
{
message: '3. Will Domestic Wires be sent or received from the account?',
value: false,
conditionalFields: [
{
fields: [
{ label: 'Frequency of Incoming Wires', value: '' }
]
},
{
fields: [
{ label: 'Frequency of Outgoing Wires', value: '' },
]
}
]
},
{
message: '4. Will International Wires be sent or received from the account?',
value: false,
conditionalFields: [
{
fields: [
{ label: 'Frequency of Incoming Wires', value: '' }
]
},
{
fields: [
{ label: 'Frequency of Outgoing Wires', value: '' },
]
}
]
},
{
message: '5. Will Monetary Instruments (CC/MO) be issued from the account?',
value: false,
conditionalFields: [
{
fields: [
{ label: 'Total Amount', value: '' }
]
}
]
}
]
}
},
validations: {
questions: {
$each: {
conditionalFields: {
$each: {
fields: {
$each: {
value: { required }
}
}
}
}
}
}
}
})
The problem is - I'm conditionally rendering fields based on the user's input. If he or she selects "Yes" to any of the questions, a secondary fieldset will appear below it and ask for input. These fields are only required if yes is selected and they appear on the DOM (and will also have different validations, which I'm not sure how to address, either without hard-coding everything). I've tried looping through the data by making validations a function, but even though it seems to compile, it's not dynamically adding any validations based on the question[index].value being set to true.
I feel like there has to be a simple way to do this, but I'm definitely overthinking it at this point. Any help would be greatly appreciated!
Thanks!

Return only non-null values from GraphQLList object

My sampleJSON -
{
"entries": [
{
"fields":{
"title":"My test title"
}
},
{
"fields":{
"description":"My test description"
}
}
]
}
Schema.js -
const rootQuery = new GraphQLObjectType({
name: 'testQuery',
fields: {
Articles: {
type: articleItem,
resolve(parentValue) {
return axios.get(`/getArticles`).then(resp => resp.data);
}
}
}
});
const articleItem = new GraphQLObjectType({
name: 'articleItem',
fields: () => ({
entries: {type: new GraphQLList(entry)}
})
});
const entry = new GraphQLObjectType({
name: 'entry',
fields: () => ({
fields: {type: fields}
})
});
const fields = new GraphQLObjectType({
name: 'fields',
fields: () => ({
title: {type: GraphQLString},
description: {type: GraphQLString}
})
});
GraphQL query i am using to query the data in the above JSON -
query articles{
Articles {
entries{
fields{
title,
description
}
}
}
}
I am wondering why the query returns "title" even though it is null in the second object and likewise with description in the first object. Is there a way to just return " title " or " description " only if it not null?
Current result of the query -
{
"data" : {
"entries" [
{
"fields": {
"title": "My test title",
"description": null
}
},
{
"fields": {
"title": null,
"description" : "My test description"
}
}
]
}
}
Required result -
{
"data" : {
"entries" [
{
"fields": {
"title": "My test title"
}
},
{
"fields": {
"description" : "My test description"
}
}
]
}
}
Appreciate any help with this !, thanks.
Way too late to answer, but if you stumble upon this, you can make non-nullable (!) by using GraphQLNonNull().
Here is the example for non-nullable integer
random: {
type: new GraphQLNonNull(GraphQLInt)
}

Mongoid: unique index for embedded documents

I'm trying to create a unique field for embedded documents:
class Chapter
include Mongoid::Document
field :title
end
class Book
include Mongoid::Document
field :name
embeds_many :chapters
index({ 'name' => 1 }, { unique: true })
index({ 'name' => 1, 'chapters.title' => 1 }, { unique: true, sparse: true })
# index({ 'name' => 1, 'chapters.title' => 1 }, { unique: true })
end
I run the task: rake db:mongoid:create_indexes
I, [2017-02-22T08:56:47.087414 #94935] INFO -- : MONGOID: Created indexes on Book:
I, [2017-02-22T08:56:47.087582 #94935] INFO -- : MONGOID: Index: {:name=>1}, Options: {:unique=>true}
I, [2017-02-22T08:56:47.087633 #94935] INFO -- : MONGOID: Index: {:name=>1, :"chapters.title"=>1}, Options: {:unique=>true, :sparse=>true}
But it doesn't work as I would expect...
Book.new( name: 'A book', chapters: [ { title: 'title1' }, { title: 'title1' }, { title: 'title2' } ] ).save # no errors
Book.new( name: 'Another book', chapters: [ { title: 'title2' } ] ).save
b = Book.last
b.chapters.push( Chapter.new( { title: 'title2' } ) )
b.save # no errors
Any idea?
UPDATE: Ruby 2.4.0, Mongo 3.2.10, Mongoid 5.2.0 | 6.0.3 (trying both)
UPDATE2: I add also the tests I made directly with mongo client:
use books
db.books.ensureIndex({ title: 1 }, { unique: true })
db.books.ensureIndex({ "title": 1, "chapters.title": 1 }, { unique: true, sparse: true, drop_dups: true })
db.books.insert({ title: "Book1", chapters: [ { title: "Ch1" }, { title: "Ch1" } ] }) # allowed?!
db.books.insert({ title: "Book1", chapters: [ { title: "Ch1" } ] })
b = db.books.findOne( { title: 'Book1' } )
b.chapters.push( { "title": "Ch1" } )
db.books.save( b ) # allowed?!
db.books.findOne( { title: 'Book1' } )
db.books.insert({ title: "Book2", chapters: [ { title: "Ch1" } ] })
UPDATE3: I made more tests but I didn't succeed, this link helped but the problem remains
You should use drop_dups
class Category
include Mongoid::Document
field :title, type: String
embeds_many :posts
index({"posts.title" => 1}, {unique: true, drop_dups: true, name: 'unique_drop_dulp_idx'})
end
class Post
include Mongoid::Document
field :title, type: String
end
Rails console:
irb(main):032:0> Category.first.posts.create(title: 'Honda S2000')
=> #<Post _id: 58adb923cacaa6f778215a26, title: "Honda S2000">
irb(main):033:0> Category.first.posts.create(title: 'Honda S2000')
Mongo::Error::OperationFailure: E11000 duplicate key error collection: mo_development.posts index: title_1 dup key: { : "Honda S2000" } (11000)

ng-repeat orderby of dynamic lenght of object

I have the following object that contains 2 fixed attributes (OrderId and Purchasedate, and an array of attribues. I try to to put this in ng-repeat with orderBy option. The first 2 attribute (OrderId and PurchaseDate) work OK when sorting is applied by clicking on the header. However I do not get it working on the 3 rd attribute and so on.
The rows shown on the table are correct.
The object looks like
e.g.
$scope.orders;
[
{ OrderId: "P888291", PurchaseDate : "2016-12-02",
Items: { elt : [ { Name: "City", Value: "New York"}, { Name: "Street", Value: "Broadway 5" }, { Name: "Country", Value: "USA" } ] } },
{ OrderId: "P334498", PurchaseDate : "2016-11-02",
Items: { elt : [ { Name: "City", Value: "London" }, { Name: "Street", Value: "WestMinister 3" }, { Name: "Country", Value: "Great Brittain" } ] } },
{ OrderId: "G393383", PurchaseDate : "2016-11-28",
Items: { elt : [ { Name: "City", Value: "Milan" }, { Name: "Street", Value: "Pizza 8" }, { Name: "Country", Value: "Italy" } ] } },
{ OrderId: "P978381", PurchaseDate : "2015-05-25",
Items: { elt : [ { Name: "City", Value: "Seattle" }, { Name: "Street", Value: "Houston 9" }, { Name: "Country", Value: "US" } ] } },
{ OrderId: "P983394", PurchaseDate : "2015-06-05",
Items: { elt : [ { Name: "City", Value: "Amsterdam" }, { Name: "Street", Value: "Damrak 5" }, { Name: "Country", Value: "Netherlands" } ] } },
{ OrderId: "G678994", PurchaseDate : "2015-04-01",
Items: { elt : [ { Name: "City", Value: "The Hague" }, { Name: "Street", Value: "Markt 22" }, { Name: "Country", Value: "Netherlands" } ] } },
{ OrderId: "P128994", PurchaseDate : "2016-12-04",
Items: { elt : [ { Name: "City", Value: "The Hague" }, { Name: "Street", Value: "Plein 7" }, { Name: "Country", Value: "Netherlands" } ] } },
];
Please advise and the code is put in :
http://www.w3schools.com/code/tryit.asp?filename=FAG7BWVK8BYH
You can try with custom filter logic.(https://docs.angularjs.org/api/ng/filter/orderBy )
for example:
JS:
$scope.filterOrderFn = function(orderobj)
{
// Do
if(...)
{
return _something_// this will be your sorted order according to your first condition
}
else if(...)
{
return _something_ // this will be your sorted order according to your second condition if require
}
return false; // otherwise it won't be within the orderlist
};
HTML:
...
<article data-ng-repeat="order in orders | orderBy:filterOrderFn" class="order">
...
If you need a very specific ordering behaviour you could write your own filter (although orderBy should be enough for most uses cases). As you may know you can chain many filters together, so adding your custom filter function doesn't force you to remove the previous filter using the search object (they will work together seamlessly).

Is there a way to union multiple nodes based on ID or Text when using Kendo tree view?

I have 3 different object / node as below, and I am trying to form the finalObj / node which is the union (unique tree list) of the 3 nodes..
Is there a method in tree view with which I can union 3 objects (nodes) based on text or id ?
First node:
[ { text: "TreeRoot", items: [
{ text: "Subgroup1" },
{ text: "Subgroup2" }
]}]
Second Node:
[ { text: "TreeRoot", items: [
{ text: "Subgroup3" }
]}]
Third node:
[{ text: "Subgroup3",
items: [ {
text: "subgroup5",
items: [ {
text: "subgroup6",
items: [ {
text: "subgroup7",
items: [ {
text: "subgroup8"
}]
}] }]
}]}]
Final expected node (after merging):
var finalObj= [ { text: "TreeRoot", items: [
{ text: "Subgroup1" },
{ text: "Subgroup2" },
{ text: "Subgroup3",
items: [ {
text: "subgroup5",
items: [ {
text: "subgroup6",
items: [ {
text: "subgroup7",
items: [ {
text: "subgroup8"
}]
}] }]
}]}]}]
EDIT:
The below solution doesnt work for other type of nodes..
For EX:
var node1 = [
{ text : "TreeRoot",
id:0,
items: [
{ text: "Subgroup1",id:1 },
{ text: "Subgroup2", id:2}
]
}
];
var node2 = [
{
text : "TreeRoot",
id:0,
items: [
{ text: "Subgroup3" ,
id:3}
]
}
];
var node3 = [
{
text : "TreeRoot",
id:0,
items: [
{
text : "Subgroup2",
id:2,
items: [
{
text : "subgroup6",
id:6,
items: [
{
text : "subgroup7",
id:7,
items: [
{
text: "subgroup8",
id:8
}
]
}
]
}
]
}
]
}
];
For above example I should see just tree root initially. When expanded I should see just subgroup1,2,3... and when subgroup2 is expanded I should be able to see subgroup6,7,8.
I need unique parent and child nodes.. If I use the above structure, I get 2 child node named- Subgroup3
Although you tag it as Kendo-UI it is actually a programming problem since there is no KendoUI interface for solving (I know that you want to use it for merging treeview nodes) it but it is not very hard solving it using recursion.
This are basically your three nodes:
var node1 = [
{ text : "TreeRoot",
items: [
{ text: "Subgroup1" },
{ text: "Subgroup2" }
]
}
];
var node2 = [
{
text : "TreeRoot",
items: [
{ text: "Subgroup3" }
]
}
];
var node3 = [
{
text : "Subgroup3",
items: [
{
text : "subgroup5",
items: [
{
text : "subgroup6",
items: [
{
text : "subgroup7",
items: [
{
text: "subgroup8"
}
]
}
]
}
]
}
]
}
];
You can merge it using the following function:
function merge(node1, node2) {
if (node2 !== null) {
if (node1.text === node2.text) {
node1.items = node1.items || [];
$.each(node2.items, function (idx2, elem2) {
var found = false;
// Check that elem does not exist on node1
$.each(node1.items, function (idx1, elem1) {
if (!found && elem1.text === elem2.text) {
found = true;
merge(elem1, elem2);
}
});
if (!found) {
node1.items.push(elem2);
}
});
} else {
if (node1.items) {
$.each(node1.items, function (idx, item) {
merge(item, node2);
});
}
}
}
}
That merges two nodes in the first one.
And you should invoke it like this:
merge(node1[0], node2[0]);
merge(node1[0], node3[0]);
for your scenario.
NOTE: I'm assuming that you only have one element on each of the nodes (i.e. node0, node1 and node2 are arrays but they only have one element)
See it running here

Resources