Создание графика с помощью Neo4j занимает слишком много времени

#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. Отлично .. выполняется за считанные секунды. Еще раз спасибо