Coloring nodes in Neo4j depending on property - colors

On the localhost page launched to use Neo4j, it is easy to color specific nodes in a different way. Following the movie example included in Neo4j; persons in red, movies in purple and with a click of the button change one to orange.
As an expansion on this, I would like to color nodes of the same type, but with a different property in a different way. Following the example; add gender as a property to each person node, followed by coloring men blue and women red.
Is it possible to realize this in the current build? I am working with Neo4j Community 2.1.7.
Edit: There was a request for an piece of the .grass file responsible for the visualization. Here is a small excerpt responsible for coloring a type of node.
node.Page {
color: #30B6AF;
border-color: #46A39E;
text-color-internal: #FFFFFF;
diameter: 80px;
border-width: 2px;
caption: '{pagename}';
font-size: 10px;}

Even though I am a bit late here want to help others who might be finding a way. It is not possible to change the color of the nodes based on the property but there is a way it can be achieved by creating nodes based on the property. Keep in mind that after applying these queries your data wont be the same. So it is always a good idea to keep a backup of your data.
This is how labels are colored by default (Before):
Color based on the property
Suppose there is a label called Case with a property nationality and you want to color the nodes based on nationality. So following query could be used to create labels out of nationality property. For this you will need to install apoc library. check here for installation.
// BY NATIONALITY
MATCH (n:Case)
WITH DISTINCT n.nationality AS nationality, collect(DISTINCT n) AS persons
CALL apoc.create.addLabels(persons, [apoc.text.upperCamelCase(nationality)]) YIELD node
RETURN *
This will return all the people by nationality. Now you can color by country of nationality. Below shows an example.
Color based on the property and load with other labels
Lets say you also have a label called Cluster.The cases are attached to clusters via relationships. Just change the query to following to get the clusters with their relationships to cases.
//BY NATIONALITY WITH CLUSTERS
MATCH (n:Case),(c:Cluster)
WITH DISTINCT n.nationality AS nationality,
collect(DISTINCT n) AS persons,
collect(DISTINCT c) AS clusters
CALL apoc.create.addLabels(persons, [apoc.text.upperCamelCase(nationality)]) YIELD node
RETURN *
It will return cases and clusters with all the relationships. Below shows example.
Please leave an up vote if this was helpful and want to let others know that this is an acceptable answer. Thank you.

I'm pretty sure this is not possible. If you click on the "Style" tab of the pop-up and click on "View stylesheet" you'll see in the GRASS file that the colors are tied to node labels. If you want a different sort of visualization, you could submit a pull request:
https://github.com/neo4j/neo4j/tree/master/community/browser
It's important to note that the GRASS format was created for Neo4j and, as far as I know, isn't used anywhere else, so don't look for standards documentation anywhere.
Alternatively, depending on what you're doing, you could create your own visualization. For the web there are a number of libraries like Sigma.js or D3. I've also been wanting to play with this one (based on Sigma.js), but haven't gotten a chance yet:
https://github.com/Linkurious/linkurious.js

I have found a workaround - virtual subgraph. Based on the APOC page:
"you can create visual representation of data that are not in the graph"
Basically you can create virtual copy of nodes using apoc.create.vNode and assign different types to those virtual nodes based on the property value. In your case there would be two new types of nodes men and women. Then you are free to assign different colour/style to the 'men' nodes and 'women' nodes.
Your code should be something like:
UNWIND ['men', 'women'] as gender
MATCH (n:Person {Gender:gender})
CALL apoc.create.vNode([gender],{id:n.id}) yield node as vPerson
RETURN vPerson
if you want to show the relationships (between same sex), comment out the last line above and add the following query:
WITH apoc.map.groupBy(collect(vPerson),'id') as vPersons, gender
WITH vPersons, [(p1:Person {Gender:gender})-[r]->(p2:Person {Gender:gender}) | apoc.create.vRelationship(vPersons[p1.id], type(r), {}, vPersons[p2.id])] as rels
RETURN vPersons, rels

Related

How to display databases values with fltk widgets

I'm developing an application - written in rust, that registers items in a database, but I'm having trouble showing the data in a way that is visually good, I tried to use the Browser widget but it's not visually appealing. I have a struct Items that store name, quantity and price, and a vector of Items that stores the field values, how can I show the items stored in the database, and what is the best widget to do that?
Natural choice would be to use the Fl_Table and Fl_Table_Row classes in your project.
Greg Ercolano has an example how to use them at https://www.seriss.com/people/erco/fltk/Fl_Table/ . In fact, he is the original author of these classes, later on they got into the FLTK itself...
Do not be confused with the screenshot when you see those buttons inside the table. - He just wanted to demonstrate that you can put any Widget in Fl_Table cells.

How to allow REST filters for non-DB fields in django

My problem is this:
I'm working on a django project that has a lot of DB tables representing many different objects. This project has a GUI interface that is mostly a table that is a rough representation of each DB table. This table I got from google images can be used as an example
Unlike this table, mine has filters on top of each column so for example you can type a name you're looking for and it will only show relevant rows. The problem starts here - Not all columns in the GUI are really columns in the DB. For example let's say the "Location" column isn't a DB column, but a property on the django model like this
#property
def location(self):
return f"{self.city}, {self.state}"
So obviously sending to my django backend this URL won't work just like that
https://mywebsite/api/people/?location__icontains=Chicago
My workaround for this is going to the View and overriding filter_queryset to handle this specific case
. Something like this:
def filter_queryset(self, queryset):
if "location__icontains" in self.request.query_params:
filter = self.request.query_params["location__icontains"]
q = Q(city__icontains=filter ) | Q(state__icontains=filter)
queryset = queryset.filter(q)
The issue is that this doesn't even really cover all cases, it only works if the user filter input is either a city or a state and not some combo like "ago, IL" (supposed to yield "Chicago, IL" in the results). Also I have too many of these cases since us developers added tones of properties or serializer fields to the display over the years and customers expect to be able to filter on them. What I'm looking for is ideally an idea to generically handle all of these (perhaps filter on the serialized entries and not on the DB rows?)
I tried to search for this problem in many different phrasing types but found no solution. For now we have to implement a hack for each specific case

finding organization and industry/sector from string in dbpedia

I am generating a short list of 10 to 20 strings which I want to lookup on dbpedia to see if they have an organization tag and if so return the industry/sector tag. I have been looking at the SPARQLwrapper queries on their website but am having trouble constructing one that returns organization and sector/industry for my string. Is there a way to do this?
If I use the code below I get a list of industry types I think rather than the industry of the company.
from SPARQLWrapper import SPARQLWrapper, JSON
sparql = SPARQLWrapper("http://dbpedia.org/sparql")
sparql.setQuery("""
SELECT ?industry WHERE
{ <http://dbpedia.org/resource/IBM> a ?industry}
""")
sparql.setReturnFormat(JSON)
results = sparql.query().convert()
Instead of looking at queries which are meant to help you understand the querying tool, you should start by looking at the data which is being queried. For instance, just click http://dbpedia.org/resource/IBM, and look at the properties (the left hand column) to see its rdf:type values (of which there are MANY)!
Note that IBM is not described as a ?industry. IBM is described as a <http://dbpedia.org/resource/Public_company> (among other things). On the other hand, IBM is also described as having three values for <http://dbpedia.org/ontology/industry> --
<http://dbpedia.org/resource/Cloud_computing>
<http://dbpedia.org/resource/Information_technology>
<http://dbpedia.org/resource/Cognitive_computing>
I don't know whether these are what you're actually looking for or not, but hopefully what I've done above will start you down the right path to whatever you do want to get out of DBpedia.

how to model colors in graph database [neo4j[

I am practicing with Neo4j. I am trying to model colors and their relationships but I don't know what to do with different names of colors.
For example, it looks like (from what I read on the internet), aqua, cyan, teal are more or less the same color.
I want to model colors such as I can classify each color in it's category (primary, secondary, tertiary), in its family (warm, cool, neutral).
I also want to represent shades, tints and tones of different colors.
How do I model that x is a tint of y and y is a primary color for example? It is becoming difficult.
I want each color to be a SEPARATE NODE.
thank you for your time.
Honestly this really depends on how you want to query your data. You could represent color as simply as a hex code or a serialized JSON string of the properties that you describe above and then you would just need a property. But if colors are a fundamental part of your model then you could get really detailed and split things out into individual nodes and relationships. I'll assume that here.
So you could have, for example, Color, Level, Family, Shade, etc... labels. For the labels after Color you could just create all of them upfront, or you could use MERGE to create them only when necessary.
Then you could simply create color nodes and relationships like:
CREATE (color:Color {hex: '#FFFFFF', name: 'White'})
and then:
MATCH (white:Color {hex: '#FFFFFF'}), (primary:Level {name: 'Primary'})
CREATE (white)-[:IS_LEVEL]->(primary)
Again, this would be if you want to query by finding common paths between colors. If you just want to be able to tell if #FFFFFF is a primary color you could have a level property with the vaule Primary.
Side note: I suggest reading Randall Munroe's color survey results blog post because it is awesome.
EDIT:
Based in your comment, if you want to have different names for a color you could either have an array property for the name (or perhaps a name property which is a string and an alternative_names property which is an array), or you could have a ColorName node with a name property and then a (:Color)-[:HAS_NAME]->(:ColorName) relationship.
One consideration if your database were to grow very large is that Neo4j doesn't yet support indexing on array properties (I think you could do it with legacy indexes, though). So something like this would work:
MATCH (color:Color) WHERE 'Red' IN color.names RETURN *
But it will need to look through ever Color node. If you had a ColorName label then you could make an index for ColorName(name). But it does come with the tradeoff that the more you extract properties into separate nodes, your queries start becoming more difficult to maintain because you need to include those extra nodes every time you want to display information about a color. You start to get into queries like;
MATCH (color:Color)
WHERE color.hex = '#FFFFFF'
OPTIONAL MATCH (color)-[:HAS_LEVEL]->(level:ColorLevel)
WITH color, level
OPTIONAL MATCH (color)-[:HAS_NAME]->(color_name:ColorName)
WITH color, level, collect(color_name.name) AS names
// etc....
RETURN color, level, names, etc...

Implementing a location search in ElasticSearch

I have a problem with location queries returning erroneous results in ElasticSearch.
In our system, a business search engine, every search takes two inputs: a location, and a query-string, e.g.
q=sushi
location=Greenwich Village, New York, New York
I want the search to show me sushi in Greenwich Village first, then sushi outside of Greenwich Village, but to never show me non-sushi results.
The problem is, because of the location query, anything in Greenwich Village gets matched -- lawyers, doctors, whatever. I'd like say the following to ElasticSearch:
If q matches, then location doesn't have to (it's OK to return sushi outside of Greenwich Village), but if location matches, don't return it unless q matches also (not OK to return non-sushi businesses in Greenwich Village).
Anyone have any thoughts on how to do this?
It sounds like you want to search for "sushi" (you don't want non-sushi results) but sort your results by location (you want Greenwich Village results first).
If you are storing locations as geo points, you can simply use distance to sort your results.
If location is just a field, and you can only know if the business is inside or outside of a location, you can use Custom Filters Score query to boost relevancy of the results in the desired location. The query part should contain the search for "sushi" and the filters part should contain the search for location.
I incorporated the information on this post and here to to come up with the following solution.
Index every 'place' (neighborhood, city, etc) with a center-point, and also index the coordinates of every business.
Index the place ids attached to the businesses that contain them.
Use a sub-search to convert the text entered into the location bar to a place record.
Use a CustomScoreQuery to modify every result's score by the following formula, which was worked out by trial and error:
new_score = old_score / (1 + distance_between_place_centerpoint_and_result)^3
Also query the place id that results from 3 against the place_ids field as a 'should' boolean query. This gives a flat boost to everything that actually falls within the confines of the specified place.
A side effect of this strategy is that businesses near the center point of the place are considered more relevant -- it is arguable, in my opinion, whether this is correct or not. But other than that it has worked quite well.
Thanks to imitov for his insight that helped me come up with this solution.

Resources