Is there a way to get a node by specific attributes using the Java API?
Specifically:
By Name
By Label
By properties - (various properties)
The only functions I found were:
findNode(label)
findNode(label, key, value)
Which only supports one property.
Or do I have to use Cypher to get this?
If your question is about how to find nodes that have specific multiple property values, the Java API has no method that does that task. In general, it is easier to use Cypher for that.
Related
Okay, I got it this question that what is the need for mapping.
Now I am going through a piece of code, what they are doing is that they are generating the mapping while creating the elastic search repository by pushing a dummy object and then deleting it.
I got it that elastic search can generate mappings, but what is the point of doing so. It does not help with the search queries ( at least the regex one that I have tried unless you explicitly tell in your mapping that this is of type keyword).
I would be thankful if someone can explain this.
Although Elasticsearch generates the mapping when you don't define one, and just index the document, but that way Elasticsearch generates the mapping based on the first document data, for example you have product-id field in your index, and if you index it without defining explicit mapping, Elasticsearch generates two data-type, one is text and another is keyword for this field when you index product-id as below.
{
"product-id" : "1"
}
Now, it depends on your use-case, let's suppose in your case, product-id is keyword and fixed, and you just want to use the exact search or aggregation on the product-id field, and don't want the full-text search, than you better go with explicit mapping and define it as in keyword field, that way Elasticsearch storage and queries would be optimal. You can refer to this Stackoverflow comment, for more information on it.
Bottomline, When you want to have a greater control on how your data should be indexed, It's always better to define explicit mapping than relaying on default mapping generated by Elasticsearch.
I've read the thread How to set DynamoDB range key, String or Map. However after some thought, I came up with more consideration.
I use jackson for serialize & deserialize object in spring app. This app was created by someone else and it's in my hand now to enhance it after its initial release.
There are 2 options to generate the partition key :
Use delimiter ( e.g. value1#value2 )
serialize to JSON ( e.g. {"field1":"value1","field2":"value2"} )
Delimiter-approach:
If I use delimiter, I can create a delimiter that very unlikely (in my case) shows up as part of value1 or value2. This approach will generate shorter string than using jackson. Also the official DynamoDB documentation give example with this approach.
However this approach means I need to document the order and rule. In case other app (e.g. Node-based or Go use the same DB, I need to tell them to read the docs.
Jackson-approach:
If I use jackson, it's quite self documented, I can use #JsonFormat to maintain formatting consistency, I can use #JsonFilter to pick which fields I want to serialize for this case. I can use #JsonProperty to shorten field name (although I doubt that I'll need to shorten field name), and also the implementation will be more robust.
But then again, in my case there's already a table that already implemented the delimiter approach. It means that there will be two different formatting needs to be written on the app documentation. Also I think that a key generation should be very explicit.
I'm a bit pros to delimiter-approach for the sake of consistent formatting, but then again I might miss or haven't see the good things from Jackson-approach, especially in the future of this project development.
My question is : should I use the delimiter-approach or the other?
I have source node and destination node I want to put restriction on nodes and relation types in the path. I am using Neo4j Java API.
Consider following toy example,
We have three person nodes A, B & C.
Source Node: A & Destination Node: B. There are many other kind of paths may exists between them. I want to restrict paths to specific format like-
(person) -[worksAt]-> (company) -[CompetitorOf]-> (company) <-[worksAt]- (person)
This can be very easily achieved from cypher query, but I want to know is there any way we can do it using Java API.
NOTE:
Kindly do not suggest putting restriction on path length, that
doesn't solve the problem. I want to restrict the node and relation
types in path.
Example mentioned above is toy example. Graph I am trying to work is more complex and there are many possible paths not feasible to traverse and validate individual paths.
It's not really clear from your question what you're actually trying to compute. Do you have A and B and want to find if their companies are competitors? Do you have C and want to find who among their friends work at competing companies?
Anyway, if you're using the traversal API (you're talking about paths), you can write a custom PathExpander which will use the last relationship in the Path to determine the next type of relationship to traverse.
If you're just traversing the relationships manually, I don't really see the problem: just call Node.getRelationships(RelationshipType, Direction) with the proper parameters at each step.
Contrary to what you do in Cypher, you don't declare the pattern you're looking for in the path, you just compute the path to follow the wanted pattern.
After reading the Neo4j java documentation carefully and experimenting with the code I got following solution working-
To filter path explored by PathFinder create a custom PathExpander using PathExpanderBuilder.
PathExpanderBuilder pathExpanderBuilder = PathExpanderBuilder.empty();
pathExpanderBuilder.add(RelationshipType.withName("worksat"), Direction.OUTGOING);
pathExpanderBuilder.add(RelationshipType.withName("competitorof"), Direction.BOTH);
pathExpanderBuilder.add(RelationshipType.withName("worksat"), Direction.INCOMING);
PathExpander<Object> pathExpander pathExpander = pathExpanderBuilder.build();
Once you create a custom PathExpander you can use it to create appropriate PathFinder which will filter traversal by the PathFinder.
PathFinder<Path> allPathFinder = GraphAlgoFactory.allSimplePaths(this.pathExpander, 4);
Iterable<Path> allPaths = allPathFinder.findAllPaths(sourceNode, targetNode);
In our example sourceNode would be Node 'A' and targetNode would be Node 'B'.
I'm using OrientDB 2.1.6 and have the following Gremling example query:
g.V("username", "testark").out("IsFriendsWith").height.mean()
This works great on the Gremlin shell, but I need to be able to use that from within Java. Using the Java Graph API I could translate most of it to
final GremlinPipeline<Long, Vertex> pipe = new GremlinPipeline<>(orientGraph);
pipe.V("username", "testark").out("IsFriendsWith").property("height").????????
but not I cannot seem to find the equivalent of the mean function. My current workaround involves computing the mean "manually" based on the return value of property, but I'd obviously prefer to get that value from the database via Gremlin. Can anyone please point out to me what's the equivalent of mean?
The mean function is a method of gremlin-groovy so you won't find it on the Java side:
https://github.com/tinkerpop/gremlin/blob/88de5e5d95bd0b704c5090c43a04a3d42992dfb9/gremlin-groovy/src/main/groovy/com/tinkerpop/gremlin/groovy/loaders/PipeLoader.groovy#L28-L35
You would need to do as you are doing and manually calculate the mean.
I know about the findNodesByLabelAndProperty method of the GraphDatabaseServiceObject, but that method requires a value parameter. In my case, I only want to know if there are any (1 or more) nodes in my database that have a specified label and property, but I don't know anything about the value of the property other than it's type. Any ideas?
Thanks
Howard
If you are using version 2.0 you could use the method getAllNodesWithLabel from class org.neo4j.tooling.GlobalGraphOperations.
GlobalGraphOperations.getAllNodesWithLabel(DynamicLabel.label("<label_name>"))
For more information: http://neo4j.com/api_docs//2.0.0-M06/org/neo4j/tooling/GlobalGraphOperations.html#getAllNodesWithLabel(org.neo4j.graphdb.Label)
Not sure I understand the question correctly, but I would just create another (boolean-valued) property for the purpose of finding the nodes.
You can create another node to store these kinds of counts- a single one with multiple properties such as "nodesWithLabelXAndPropertyY" with the count as the value which you can set at the end of your algorithm run. Or just a boolean exists/not exists value.
Then all you need to do is query this node for summary statistics.