Как я могу эффективно создавать уникальные отношения в Neo4j?

В продолжение моего вопросаВотЯ хотел бы создать ограничение на отношения. То есть я хотел бы, чтобы было несколько узлов, которые имеют одно и то же имя «соседства», но каждый из них однозначно указывает на определенный город, в котором они проживают.

Как рекомендуется в user2194039'sответЯ использую следующий индекс:

CREATE INDEX ON :Neighborhood(name)

Кроме того, у меня есть следующее ограничение:

CREATE CONSTRAINT ON (c:City) ASSERT c.name IS UNIQUE;

Следующий код не может создать уникальные отношения и занимает слишком много времени:

USING PERIODIC COMMIT 10000
LOAD CSV WITH HEADERS FROM "file://THEFILE" as line
WITH line
WHERE line.Neighborhood IS NOT NULL
WITH line
MATCH (c:City { name : line.City})
MERGE (c)<-[:IN]-(n:Neighborhood {name : toInt(line.Neighborhood)});

Обратите внимание, что существует ограничение уникальности для города, но НЕ для соседства (потому что должно быть несколько).

Профиль с лимитом 10000:

+--------------+------+--------+---------------------------+------------------------------+
|     Operator | Rows | DbHits |               Identifiers |                        Other |
+--------------+------+--------+---------------------------+------------------------------+
|  EmptyResult |    0 |      0 |                           |                              |
|  UpdateGraph |    9750 |      3360 | anon[307], b, neighborhood, line |                 MergePattern |
|  SchemaIndex |    9750 |      19500 |                   b, line | line.City; :City(name) |
| ColumnFilter |    9750 |      0 |                      line |            keep columns line |
|       Filter |    9750 |      0 |           anon[220], line |                    anon[220] |
|      Extract |    10000 |      0 |           anon[220], line |                    anon[220] |
|        Slice |    10000 |      0 |                      line |                 {  AUTOINT0} |
|      LoadCSV |    10000 |      0 |                      line |                              |
+--------------+------+--------+---------------------------+------------------------------+

Всего обращений к базе данных: 22860

Следуя рекомендации Гильерма, приведенной ниже, я реализовал помощник, но он вызывает ошибку py2neo.error.Finished. Я искал документацию и не смог определить обходной путь отэтот, Похоже, что естьоткрой ТАК об этом исключении.

def run_batch_query(queries, timeout=None):
if timeout:
    http.socket_timeout = timeout
try:
    graph = Graph()
    authenticate("localhost:7474", "account", "password")
    tx = graph.cypher.begin()
    for query in queries:
        statement, params = query
        tx.append(statement, params)
        results = tx.process()
        tx.commit()
except http.SocketError as err:
    raise err
except error.Finished as err:
    raise err
collection = []
for result in results:
    records = []
    for record in result:
        records.append(record)
    collection.append(records)  
return collection

главный:

queries = []
template = ["MERGE (city:City {Name:{city}})", "Merge (city)<-[:IN]-(n:Neighborhood {Name : {neighborhood}})"]
statement = '\n'.join(template)
batch = 5000
c = 1
start = time.time()

# city_neighborhood_map is a defaultdict that maps city-> set of neighborhoods
for city, neighborhoods in city_neighborhood_map.iteritems():
    for neighborhood in neighborhoods:
        params = dict(city=city, neighborhood=neighborhood)
        queries.append((statement, params))
        c +=1
        if c % batch == 0:
            print "running batch"
            print c
            s = time.time()*1000
            r = run_batch_query(queries, 10)
            e = time.time()*1000
            print("\t{0}, {1:.00f}ms".format(c, e-s))
            del queries[:]

print c
if queries:
    s = time.time()*1000 
    r = run_batch_query(queries, 300)
    e = time.time()*1000
    print("\t{0} {1:.00f}ms".format(c, e-s))
end = time.time()
print("End. {0}s".format(end-start))

Ответы на вопрос(2)

Ваш ответ на вопрос