Статьи

Crunchbase на Neo4j

NeoTechnology был представлен на TechCrunch после поднятия раунда серии B , и он имеет запись на CrunchBase . Если вы внимательно посмотрите на CrunchBase, то заметите, что это график. Кто во что инвестировал, кто соинвестировал, каковы общие темы инвестирования между инвесторами, как компании связаны между собой членами совета директоров и т. Д. Это вопросы, которые мы можем задать для графика и которые хорошо подходят для графических баз данных.

Итак, давайте вернемся к этому. Этот проект и набор данных доступны на Github , но если вы хотите воспроизвести его самостоятельно, вам нужно зарегистрироваться на http://developer.crunchbase.com и получить ключ API. После того, как у вас есть один, вы можете взглянуть на возвращенный JSON, перейдя в IO Docs . Вот часть записи компании «нео-технологии».

{
"name": "Neo Technology",
"permalink": "neo-technology",
"crunchbase_url": "http://www.crunchbase.com/company/neo-technology",
"homepage_url": "http://www.neotechnology.com",
"blog_url": "",
"blog_feed_url": "",
"twitter_username": "",
"category_code": "software",
"number_of_employees": null,
"founded_year": 2007,
"founded_month": null,
"founded_day": null,
"deadpooled_year": null,
"deadpooled_month": null,
"deadpooled_day": null,
"deadpooled_url": null,
"tag_list": "graphs, open-soure-graphs, graph-systems, commercial-graphs, graph-database",
"alias_list": "",
"email_address": "",
"phone_number": "",
"description": "Graph Database",
 ...

Я не собираюсь отображать все CrunchBase, но я возьму несколько интересных вещей. Я импортирую компании, людей, финансовые организации и теги как Узлы, а также связи сотрудников, инвесторов, тегов и конкурентов как Отношения в Neo4j .

Я использую замечательный драгоценный камень CrunchBase от Tyler Cunnion . Я начинаю с получения всех сущностей, которые меня интересуют (например, это Люди):

all_people = Crunchbase::Person.all
 all_people.each do |ap|
   begin
     next unless ap.permalink
     file = "crunchbase/people/#{ap.permalink}"
     if File.exist?(file)
       person = Marshal::load(File.open(file, 'r'))
     else
       person = ap.entity
       File.open(file, 'wb') { |fp| fp.write(Marshal::dump(person)) }      
     end

     people << {:name => "#{person.first_name || ""} #{person.last_name || ""}",
                :permalink      => person.permalink,
                :crunchbase_url => person.crunchbase_url || "",
                :homepage_url   => person.homepage_url || "",
                :overview       => person.overview || ""
                }

   rescue Exception => e   
     puts e.message
   end    

 end

Я сохраняю JSON, возвращенный из CrunchBase API, в файл на случай, если что-то пойдет не так, и мне нужно перезапустить импорт. Neo4j не любит нулевые значения для свойств, поэтому на всякий случай я использую пустую строку, если значение не найдено.

Я буду использовать полнотекстовый индекс lucene, чтобы люди могли найти свою любимую компанию, человека, метку или финансовую организацию по постоянной ссылке, поэтому сначала создадим ее.

neo = Neography::Rest.new
neo.create_node_index("node_index", "fulltext", "lucene") 

Затем я буду создавать узлы для этих сущностей (при сохранении идентификатора узла, возвращенного в хеш):

people_nodes = {}
people.each_slice(100) do |slice|
  commands = []
  slice.each_with_index do |person, index|
    commands << [:create_unique_node, 
                 "node_index", 
                 "permalink", 
                 person[:permalink], 
                 person]
  end

  batch_results = neo.batch *commands

  batch_results.each do |result|
    people_nodes[result["body"]["data"]["permalink"]] = result["body"]["self"].split('/').last
  end
end

Я использую Neo4j Rest Batch метод отправки 100 команд одновременно.

Затем я создаю отношения друг с другом. Например сотрудники компаний:

employees.each_slice(100) do |slice|
  commands = []
  slice.each do |employee|
    commands << [:create_relationship, 
                 employee[:type], 
                 people_nodes[employee[:from]], 
                 company_nodes[employee[:to]], 
                 employee[:properties]] 
  end
  batch_results = neo.batch *commands  
end

Для внешнего интерфейса мне нужны два основных метода. Один вернет все узлы и типы отношений, связанные с одним узлом:

cypher = "START me=node(#{params[:id]}) 
          MATCH me -[r?]- related
          RETURN me, r, related"

connections = neo.execute_query(cypher)["data"]

Второй запрос обрабатывает полнотекстовый поиск и форматирует выходные данные в хэш JSON, с которым JQuery Autocomplete может работать:

get '/search' do 
  content_type :json
  neo = Neography::Rest.new    

  cypher = "START me=node:node_index({query}) 
            RETURN ID(me), me.name
            ORDER BY me.name
            LIMIT 15"
  query = "permalink:*#{params[:term]}* OR name:*#{params[:term]}*"
  neo.execute_query(cypher, 
                    {:query => query })["data"].
                      map{|x| 
                           { label: x[1], 
                             value: x[0] }
                         }.to_json   
end

Обратите внимание, как я передаю весь запрос Lucene в качестве параметра? Это правильный способ сделать это. Я индексировал людей, компании и финансовые организации по постоянной ссылке, но индексировал теги по имени. Я использую предложение «ИЛИ», чтобы захватить их обоих.

Вы можете пропустить этап построения графика, если вы просто хотите использовать данные в том виде, в каком они существовали в день публикации этого блога, поскольку они доступны в репозитории github .

Вы можете клонировать репозиторий, создать приложение heroku и быстро его запустить.

git clone https://github.com/maxdemarzi/neo_crunch.git
cd neo_crunch
heroku apps:create
heroku addons:add neo4j:try
git push heroku master

Затем перейдите в свои приложения Heroku https://dashboard.heroku.com/apps/

Найдите свое приложение и перейдите в дополнение к Neo4j.

В разделе «Резервное копирование и восстановление» нажмите «Выбрать файл», найдите файл crunchbase.zip и нажмите «Отправить». Загрузка данных займет некоторое время, но как только вы сможете перейти к своему приложению и увидеть это:

Нажмите на изображение выше, чтобы увидеть его живую версию.