how to use the timestamp() cypher function in py2neo? - neo4j

I've been running this cypher
CREATE (b:Request {created_at: timestamp(), depth:$depth})"
which relies on the cypher timestamp() function.
The documentation calls out
The timestamp() function returns the equivalent value of datetime().epochMillis.
meaning I could do the time calculation on the server-side,
though having access to the scalar functions I'd like to know if it's A) possible, and B) if possible how to use.
b = Node("Request", created_at= timestamp(), depth= 0) did not even a little bit work.

Note that if you do this, you are generating a timestamp client-side rather than server-side and you should be aware of the implications of this, re clock sync, etc.
That said, you'll need to pass an actual Python datetime instance (Cypher can only be evaluated server-side):
from datetime import datetime
b = Node("Request", created_at=datetime.now(), depth=0)
You'll need to make sure you're running at least py2neo 4.2 and Neo4j 3.4 for this to be available.

Related

How to express multiple property set criteria for node selection using gremlin query

Here is my simplified graph schema,
package:
property:
- name: str (indexed)
- version: str (indexed)
I want to query the version using multiple set of property criteria within single query. I can use within for a list of single property, but how to do it for multiple properties?
Consider I have 10 package nodes, (p1,v1, p2,v2, p3,v3,.. p10,v10)
I want to select only nodes which has (p1 with v1, p8 with v8, p10 with v10)
Is there a way to do with single gremlin query?
Something equivalent to SELECT * from package WHERE (name, version) in ((p1,v1),(p8,v8),(p10,v10)).
It's always best to provide some sample data when asking questions about Gremlin. I assume that this is an approximation of what your model is:
g.addV('package').property('name','gremlin').property('version', '1.0').
addV('package').property('name','gremlin').property('version', '2.0').
addV('package').property('name','gremlin').property('version', '3.0').
addV('package').property('name','blueprints').property('version', '1.0').
addV('package').property('name','blueprints').property('version', '2.0').
addV('package').property('name','rexster').property('version', '1.0').
addV('package').property('name','rexster').property('version', '2.0').iterate()
I don't think that there is a way that you can compare pairs of inputs and expect an index hit. You therefore have to do what you normally do in graphs and choose the index to best narrow your results before you filter in memory. I would assume that in your case this would be the "name" property, therefore grab those first then filter the pairs:
gremlin> g.V().has('package','name', within('gremlin','blueprints')).
......1> elementMap().
......2> where(select('name','version').is(within([name:'gremlin',version:'2.0'], [name:'blueprints',version:'2.0'])))
==>[id:3,label:package,name:gremlin,version:2.0]
==>[id:12,label:package,name:blueprints,version:2.0]
this might not be the most "creative" way of doing that,
but I think that the easiest way would be to use or:
g.V().or(
hasLabel('v1').has('prop', 'p1'),
hasLabel('v8').has('prop', 'p8'),
hasLabel('v10').has('prop', 'p10')
)
example: https://gremlify.com/6s

how can I refactor this py2neo v4 code to use neo4j 3.4 temporal data types?

I'm stuck trying to add a date_accepted property to an upload node that represents a scientific paper. Previously, I would have just added a timetree node. However, py2neo v4 no longer supports GregorianCalendar (shame). How would I convert this code snippet to use one of the new temporal data types? I've looked at the docs & online but I'm not yet savvy enough I'm afraid.
from datetime import date, datetime # ??? how to use this...
def getAccepted(year_accepted, month, day):
with open('/home/pmy/pdf/id.txt') as f:
id = f.read()
matcher = NodeMatcher(graph)
upload = matcher.match("Upload", id = id).first()
a = year_accepted+month+day
d = datetime.strptime(a, '%Y%m%d').strftime('%Y-%m-%d')
# >>> HOW TO CONVERT d TO A TEMPORAL DATA TYPE HERE? <<<
try:
graph.merge(upload)
upload['accepted_date']=d
graph.push(upload)
except IndexError as e:
print("type error: " + str(e))
pass
return 0
This works but it pushes the datetime string whereas I want to push a neotime temporal date...
It is possible to insert the datetime variable d above into something like this query below, which also works, but I'm winging this & suspect there's a better way...
query='''UNWIND [date({param})] AS date RETURN date'''
result=graph.run(query, param=d).data()
print(result)
which returns
[{'date': neotime.Date(2010, 10, 23)}]
So I could maybe extract the value & push that to the graph? Is this what the developers intended? The Docs are terse and aimed at proper programmers so IDK
Maybe
accepted=result[0].get('date') # <class 'neotime.Date'>
& push that to the graph perhaps?
The py2neo v4 neotime temporal types are very recent & there is not much documentation, or basic tutorials to adapt afaik. Hence this long-winded post. Anyone out there with experience care to comment?
Another user posted a similar question here: https://stackoverflow.com/a/61989193/13593049
Essentially, you need to use the neotime package for your dates and times if you want to use Neo4j data types in your graph. (Documentation)
neotime also has functionality to convert neotime objects into datetime objects.
import neotime
date_accepted = neotime.Date(2020, 05, 25)
print(date_accepted.to_native())
# # datetime.date(2020, 5, 25)

Neo4J 3.4 how does `date` function work?

I upgraded a Neo4J v3.3 to v3.4 to try out the new spatial and temporal functions.
I'm trying very simple queries. Once with the date function and one without. The results are different.
match (r:Model) where r.open_date>"2018-04-26" return count(r);
Result is 19283.
match (r:Model) where r.open_date>date("2018-04-26") return count(r);
Result is 0.
What is the way to use the new functions?
[EDITED]
The new temporal types, like Date and Duration, are really special types, and it does not make sense to compare them directly to strings or numbers.
Assuming r.open_date has the right format, this should work:
MATCH (r:Model)
WHERE DATE(r.open_date) > DATE("2018-04-26")
RETURN
Also, the the following query may be more performant (since a second DATE object does not need to be constructed):
MATCH (r:Model)
WHERE TOSTRING(DATE(r.open_date)) > "2018-04-26"
RETURN

Neo4j SDN 4 emulate sequence object(not UUID)

Is it possible in Neo4j or SDN4 to create/emulate something similar to a PostgreSQL sequence database object?
I need this thread safe functionality in order to be able to ask it for next, unique Long value. I'm going to use this value as a surrogate key for my entities.
UPDATED
I don't want to go with UUID because I have to expose these IDs within my web application url parameters and in case of UUID my urls look awful. I want to go with a plain Long values for IDs like StackOverflow does, for example:
stackoverflow.com/questions/42228501/neo4j-sdn-4-emulate-sequence-objectnot-uuid
This can be done with user procedures and functions. As an example:
package sequence;
import org.neo4j.procedure.*;
import java.util.concurrent.atomic.AtomicInteger;
public class Next {
private static AtomicInteger sequence = new AtomicInteger(0);
#UserFunction
public synchronized Number next() {
return sequence.incrementAndGet();
}
}
The problem of this example is that when the server is restarted the counter will be set to zero.
So it is necessary to keep the last value of the counter. This can be done using these examples:
https://maxdemarzi.com/2015/03/25/triggers-in-neo4j/
https://github.com/neo4j-contrib/neo4j-apoc-procedures/blob/master/src/main/java/apoc/trigger/Trigger.java
No. As far as I'm aware there isn't any similar functionality to sequences or auto increment identifiers in Neo4j. This question has also been asked a few times in the past.
The APOC project might be worth checking out for this though. There seems to be a request to add it.
If your main interest is in having a way to generate unique IDs, and you do not care if the unique IDs are strings, then you should consider using the APOC facilities for generating UUIDs.
There is an APOC function that generates a UUID, apoc.create.uuid. In older versions of APOC, this is a procedure that must be invoked using the CALL syntax. For example, to create and return a single Foo node with a new UUID:
CREATE (f:Foo {uuid: apoc.create.uuid()})
RETURN f;
There is also an APOC procedure, apoc.create.uuids(count), that generates a specified number of UUIDs. For example, to create and return 5 Foo nodes with new UUIDs:
CALL apoc.create.uuids(5) YIELD uuid
CREATE (f:Foo {uuid: uuid})
RETURN f;
The most simplest way in Neo4j is to disable ids reuse and use node Graph ID like sequencer.
https://neo4j.com/docs/operations-manual/current/reference/configuration-settings/
Table A.83. dbms.ids.reuse.types.override
Description: Specified names of id types (comma separated) that should be reused. Currently only 'node' and 'relationship' types are supported.
Valid values: dbms.ids.reuse.types.override is a list separated by "," where items are one of NODE, RELATIONSHIP
Default value: [RELATIONSHIP, NODE]

NEO4J execute severals statement

How it's possible to run a collection of query like this (came from a spreadsheet copy) directly in one cypher query? one by one it's ok, but need 100 copy/paste
*******************************
MATCH (c:`alpha`)
where c.name = "a-01"
SET c.CP_PRI=1, c.TO_PRI=1, c.TA_PRI=2
return c ;
MATCH (c:`beta`)
where c.name = "a-02"
SET c.CP_PRI=1, c.TO_PRI=1, c.TA_PRI=0
return c ;
and 100 other lines ...
*********************************
you may try the 'union' clause, which joins the results of queries into one big-honkin result set:
http://docs.neo4j.org/chunked/milestone/query-union.html
That said - the root behavior of what you are trying to do could use some details - maybe there's a better way to write the query - you could use Excel to 'build' the unified query via calculations / macros, you could possibly write a unified query that combines the rules you are trying to follow, there's a lot of options, but it's hard to know a starting direction w/o context....
Talking about the REST API you can use the transactional endpoint in Neo4J 2.0, or the batch endpoint in Neo4J 1.x.
If you want to use the shell, have a look to the import page, in particular the neo4j-shell-tools where they're importing massive quantity of data batching multiple queries.

Resources