2016-06-30 2 views
1

У меня возникли проблемы с импортом очень большого файла XML с 36196662 строк. Я пытаюсь создать базу данных Neo4j Graph этого XML-файла с Py2neo мой XML-файл выглядеть:Импорт большого файла xml в Neo4j с Py2neo

http://imgur.com/pLylHeG

и мой код Python импортировать XML-данные в Neo4j как то:

from xml.dom import minidom 
from py2neo import Graph, Node, Relationship, authenticate 
from py2neo.packages.httpstream import http 
http.socket_timeout = 9999 
import codecs 

authenticate("localhost:7474", "neo4j", "******") 

graph = Graph("http://localhost:7474/db/data/") 

xml_file = codecs.open("User_profilesL2T1.xml","r", encoding="latin-1") 

xml_doc = minidom.parseString (codecs.encode (xml_file.read(), "utf-8")) 

#xml_doc = minidom.parse(xml_file) 
persons = xml_doc.getElementsByTagName('user') 
label1 = "USER" 

# Adding Nodes 
for person in persons: 


    if person.getElementsByTagName("id")[0].firstChild: 
     Id_User=person.getElementsByTagName("id")[0].firstChild.data 
    else: 
     Name="NO ID" 
    print ("******************************USER***************************************") 
    print(Id_User) 



    print ("*************************") 
    if person.getElementsByTagName("name")[0].firstChild: 
     Name=person.getElementsByTagName("name")[0].firstChild.data 
    else: 
     Name="NO NAME" 
    # print("Name :",Name) 


    print ("*************************") 
    if person.getElementsByTagName("screen_name")[0].firstChild: 
     Screen_name=person.getElementsByTagName("screen_name")[0].firstChild.data 
    else: 
     Screen_name="NO SCREEN_NAME" 
    # print("Screen Name :",Screen_name) 

    print ("*************************") 
    if person.getElementsByTagName("location")[0].firstChild: 
     Location=person.getElementsByTagName("location")[0].firstChild.data 
    else: 
     Location="NO Location" 
# print("Location :",Location) 


    print ("*************************") 
    if person.getElementsByTagName("description")[0].firstChild: 
     Description=person.getElementsByTagName("description")[0].firstChild.data 
    else: 
     Description="NO description" 
    # print("Description :",Description) 


    print ("*************************") 
    if person.getElementsByTagName("profile_image_url")[0].firstChild: 
     Profile_image_url=person.getElementsByTagName("profile_image_url")[0].firstChild.data 
    else: 
     Profile_image_url="NO profile_image_url" 
    # print("Profile_image_url :",Profile_image_url) 

    print ("*************************") 
    if person.getElementsByTagName("friends_count")[0].firstChild: 
     Friends_count=person.getElementsByTagName("friends_count")[0].firstChild.data 
    else: 
     Friends_count="NO friends_count" 
# print("Friends_count :",Friends_count) 


    print ("*************************") 
    if person.getElementsByTagName("url")[0].firstChild: 
     URL=person.getElementsByTagName("url")[0].firstChild.data 
    else: 
     URL="NO URL" 
    # print("URL :",URL) 






    node1 = Node(label1,ID_USER=Id_User,NAME=Name,SCREEN_NAME=Screen_name,LOCATION=Location,DESCRIPTION=Description,Profile_Image_Url=Profile_image_url,Friends_Count=Friends_count,URL=URL) 
    graph.merge(node1) 

Моя проблема в том, когда я запускаю код, это займет много времени, чтобы импортировать этот файл почти неделю, чтобы сделать это, так что если кто-нибудь может помочь мне импортировать больше данных быстрее, чем я буду очень благодарен ,

NB: Моя конфигурация ноутбук: 4Gb RAM, 500Gb жесткий диск, i5

ответ

1

Если импорт данных в новую базу данных, вы можете попробовать импорт-инструмент: https://neo4j.com/docs/operations-manual/current/#import-tool

В этом случае вы должны проанализировать свой XML-файл, как вы уже это сделали, но вместо того, чтобы использовать py2neo для вставки данных в Neo4j, просто напишите CSV-файл и затем вызовите инструмент импорта.

Ниже возможный способ сделать это:

import csv 
from xml.dom import minidom 

def getAttribute(node,attribute,default=None): 
    attr = node.getElementsByTagName(attribute)[0] 
    return attr.firstChild.data if attr.firstChild else default 

xml_doc = minidom.parse(open("users.xml")) 
persons = xml_doc.getElementsByTagName('user') 

users = [] 
attrs = ['name','screen_name','location','description','profile_image_url','friends_count','url'] 

mapping = {'user_id': 'user_id:ID(User)', 
      'name': 'name:string', 
      'screen_name': 'screen_name:string', 
      'location': 'location:string', 
      'description': 'description:string', 
      'profile_image_url': 'profile_image_url:string', 
      'friends_count': 'friends_count:int', 
      'url': 'url:string'} 

with open('users.csv','w') as csvfile: 
    writer = csv.DictWriter(csvfile, fieldnames=mapping.values()) 
    writer.writeheader() 
    for person in persons: 
     user = {mapping[attr]: getAttribute(person, attr) for attr in attrs} 
     user[mapping['user_id']] = getAttribute(person, 'id') 

     writer.writerow(user) 

После того, как вы превратили XML в файл CSV, запустить импорт-инструмент:

$ neo4j-import --into neo4j-community-3.0.3/data/databases/users.db --nodes:User users.csv 

Я думаю, вы также хотите, для создания связей между узлами (?). Вы должны прочитать документы-инструменты импорта и вызвать импорт-инструмент с файлами csv для обоих узлов и отношениями

+0

Спасибо Санчо за ваш ответ, но я не знаю, как это сделать, если вы можете предложить мне код, чтобы сделать это, было бы очень приятно. –

+0

Я только что отредактировал свой предыдущий ответ на примере. Я надеюсь, что это помогает. – sancho

+0

Большое спасибо Sancho за вашу помощь –

1

Я думаю, вам следует использовать потоковый анализатор, иначе может быть даже на стороне python, что вы переполняете память.

Также я рекомендую совершать транзакции в Neo4j с партиями от 10 к до 100 тыс. Обновлений за транзакцию.

Не размещайте поля "NO xxxx", просто оставьте их, это просто пустая трата пространства и усилий.

Я не знаю, как работает слияние (узел). Я рекомендую создать уникальное ограничение на: Пользователь (USERID) и используя Cypher запрос, как это:

UNWIND {data} as row 
MERGE (u:User {userId: row.userId}) ON CREATE SET u += {row} 

где {data} параметр списка (например, 10к записей) словарей со свойствами.

+0

Спасибо, Майкл за ваш ответ. О вашей рекомендации, как я могу это сделать с py2neo, если вы можете мне помочь в коде, я буду очень благодарен. –

Смежные вопросы