#python-2.7 #neo4j
#python-2.7 #neo4j
Вопрос:
Я новичок в Neo4j и Python и пытаюсь заполнить тестовую базу данных узлами и связями, используя IPython. Я использую py2neo v 3.1.2. Проблема, которую я пытаюсь решить, заключается в представлении набора предложений в графе с идентификатором предложения, связанным с содержащимися словами через ссылки, имеющие количество слов в качестве свойства.
Я добавил соответствующие ограничения Neo4j как для строки (num), так и для слова (val). Соответствующий код приведен здесь:
from py2neo import Graph, Node, Path
import re
graph = Graph("http://neo4j:xxxx@localhost:7474/db/data/")
f1 = open("test.txt", "r")
cnt = 0
for line in f1:
cnt = cnt 1
line=line.lower()
line = re.sub(r'[^ws]','',line)
wordlist = line.split()
lgth = len(wordlist)
wordfreq = [wordlist.count(w) for w in wordlist]
dct = dict(zip(wordlist,wordfreq))
str = Node("String", num=cnt, length = lgth)
graph.merge(str)
for k, v in dct.items():
wrd = Node("Word", val=k)
graph.merge(wrd)
property_dict = {"wrdcnt": v}
relate = Path(str, ("CONTAINS",property_dict),wrd)
graph.merge(relate)
Для заполнения небольшого набора из 1000 строк в виде графика в Neo4j требуется около 10 минут. Я уверен, что я делаю что-то неправильно в своем коде на Python, и то же самое можно значительно ускорить. Был бы признателен за любую значимую информацию..
Комментарии:
1. Вы провели сравнительный анализ только вашего синтаксического анализа? Также: вы выполняете значительное количество слияний. Возможно, отредактируйте свой вопрос, чтобы показать основные запросы Cypher, которые вы будете запускать при импорте.
2. Я провел сравнительный анализ. код python выполняется за секунду
Ответ №1:
Вы выполняете 2 запроса на слово в каждом предложении, плюс еще один запрос на предложение; это занимает много времени, потому что вы несете огромные накладные расходы, используя эти py2neo
удобные методы. Вы можете сократить путь до одного запроса на предложение, если используете параметры и выполняете больше работы с Cypher:
from collections import Counter
from string import maketrans, punctuation
no_punc = maketrans(punctuation, ' ' * len(punctuation))
with open('test.txt', 'r') as f1:
for ct, line in enumerate(f1):
line = line.lower().translate(no_punc).split()
length = len(line)
dct = Counter(line)
graph.run('''
MERGE (s:Sentence { id:{count}, length: {s_length} })
WITH s
UNWIND keys({dct}) AS word
MERGE (w:Word { id: word })
MERGE (s) - [:CONTAINS {wrdcnt: {dct}[word] }] -> (w)''',
parameters={'dct': dct, 's_length': length, 'count': ct})
RABBITHOLE: это все, что выполняется в одном запросе. Это не красиво, но потенциально самый быстрый. Кроме того, убедитесь, что у вас включены индексы :Sentence(id)
, и :Word(id)
в любом случае это значительно ускорит оба.
from collections import Counter
from string import maketrans, punctuation
no_punc = maketrans(punctuation, ' ' * len(punctuation))
params = []
with open('test.txt', 'r') as f1:
for ct, line in enumerate(f1):
line = line.lower().translate(no_punc).split()
length = len(line)
dct = Counter(line)
params.append({'dct': dct, 's_length': length, 'count': ct})
graph.run('''
UNWIND {params} AS param
WITH param['dct'] AS dct, param['count'] AS ct, param['s_length'] AS s_length
MERGE (s:Sentence { id: ct, length: s_length })
WITH s, dct
UNWIND keys(dct) AS word
MERGE (w:Word { id: word })
MERGE (s) - [:CONTAINS {wrdcnt: dct[word] }] -> (w)''',
parameters={'params': params})
Комментарии:
1. В IPython выдается следующая ошибка — CypherSyntaxError: между MERGE и UNWIND требуется WITH
2. да, это каждый раз меня ловит. Это исправлено выше.
3. Спасибо, это ускорило program..it теперь требуется менее 2 минут для 1000 строк (6334 узла, 21777 отношений). Но интересно, можно ли это улучшить. Ранее я пытался импортировать форматы csv с полумиллионом узлов менее чем за 5 минут. Однако текущая задача ориентирована на текст
4. Импорт CSV позволяет осуществлять потоковую передачу и выполняет весь его синтаксический анализ внутри Cypher, и в результате получается очень быстро. Вы можете поместить все это в один оператор запроса, но это будет некрасиво… смотрите выше.
5. Отлично .. выполняется за считанные секунды. Еще раз спасибо