Статьи

Моя заявка на участие в конкурсе HCIR

Твит от RiparianData привлек мой взгляд на днях:

Я создал getvouched.com с этой идеей «экспертизы и экспертизы», используя ручное управление, основанное на навыках, отрегулированное расстоянием от искателя до цели, как способ найти ранг. Так что я покопался и обнаружил, что поиск информации о человеке и компьютере (HCIR) объединяет исследования в области взаимодействия человека с компьютером (HCI) и поиска информации (IR), делая упор на участие человека в поисковой деятельности.

Задача HCIR для симпозиума этого года включает «наем», «составление программы конференции» и «поиск людей для проведения патентных исследований или показаний экспертов», как резюмировал Патрик Дурусау .

Я опоздал на вечеринку (поскольку крайний срок для получения доступа к данным Mendeley прошел), но Уильям Ганн и Даниэль Тункеланг были достаточно любезны, чтобы предоставить мне доступ.

Я получил данные через Dropbox, в основном это данные, разделенные табуляцией, за одним исключением — дамп JSON публикаций.

Мне нужно было импортировать это в Neo4j, поэтому я следовал примерам из Batch Importer Часть 2 и Batch Importer Часть 3 для создания ETL, но сначала мне нужно было загрузить данные в Postgresql, чтобы я мог сопоставить два формата. Я обрисовал в общих чертах, как я сделал это на репозитории HCIR github .

В итоге я получил этот график:

publication -[:by_discipline]->      discipline 
publication -[:by_country]->         country
publication -[:by_academic_status]-> academic_status
publication -[:authored_by]->        author
publication -[:published_in]->       journal
author      -[:has_profile]->        profile
profile     -[:interested_in]->      discipline      
profile     -[:member_of]->          group
profile     -[:knows]->              profile

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

START authors = node:vertices('type:author')
RETURN authors.name
LIMIT 3;

Хорошо смотритесь:

==> +------------------+
==> | authors.name     |
==> +------------------+
==> | "Dominik Papies" |
==> | "Felix Eggers"   |
==> | "Nils Wlömert"   |
==> +------------------+

Интересно, кто самый плодовитый автор?

START authors = node:vertices('type:author') 
MATCH authors <-[:authored_by]- publication
RETURN authors.name, count(publication) AS cnt
ORDER BY cnt DESC
LIMIT 5;

«Тимоти Э Хьюитт» является автором большинства публикаций в нашем наборе данных.

==> +--------------------------+
==> | authors.name       | cnt |
==> +--------------------------+
==> | "Timothy E Hewett" | 339 |
==> | "Gregory D Myer"   | 226 |
==> | "Kevin R Ford"     | 202 |
==> | "Felix Gugerli"    | 144 |
==> | "K Darowicki"      | 143 |
==> +--------------------------+

Интересно, сколько у него соавторов?

START author = node:vertices('type:author AND name:"Timothy E Hewett"') 
MATCH author <-[:authored_by]- publication -[:authored_by]-> co_authors
RETURN count(DISTINCT co_authors);

Это тонна соавторов.

==> +----------------------------+
==> | count(DISTINCT co_authors) |
==> +----------------------------+
==> | 280                        |
==> +----------------------------+

Давайте выберем одного автора сверху и сосредоточимся на них.

START me = node:vertices('name:"Felix Eggers"')
RETURN me;

Похоже, он у нас есть как автор, и у нас есть его профиль.

==> +-------------------------------------------------------------------+
==> | me                                                                |
==> +-------------------------------------------------------------------+
==> | Node[17]{name:"Felix Eggers",type:"author",node_id:"17"}          |
==> | Node[400573]{name:"Felix Eggers",type:"profile",node_id:"400573"} |
==> +-------------------------------------------------------------------+

Допустим, что Феликс пытается нанять кого-то вроде него или собрать программу конференции по интересующей его теме. Мы можем попытаться найти людей, похожих на Феликса, несколькими способами:

По контактам:

Мы можем начать с простого случая, кого знает Феликс?

START me = node:vertices('type:profile AND name:"Felix Eggers"')
MATCH me -[:knows]-> profiles
RETURN DISTINCT profiles.name
LIMIT 5; 

5 из 7 авторов Феликс знает:

==> +-------------------+
==> | profiles.name     |
==> +-------------------+
==> | "Jens Hogreve"    |
==> | "Mathias Lin"     |
==> | "Fabian Eggers"   |
==> | "Tillmann Wagner" |
==> | "Andreas Neus"    |
==> +-------------------+

Феликс не знает многих других авторов, давайте расширим его сеть еще на один уровень.

START me = node:vertices('type:profile AND name:"Felix Eggers"')
MATCH me -[:knows]-> () -[:knows]-> profiles
RETURN DISTINCT profiles.name;
LIMIT 5; 

5 из 16 контактов его контакты знают:

==> +------------------------+
==> | profiles.name          |
==> +------------------------+
==> | "Victor Henning"       |
==> | "Jens Hogreve"         |
==> | "Charles Hofacker"     |
==> | "Stephanie Feiereisen" |
==> | "Alexander Stich"      |
==> +------------------------+

Члены тех же групп:

Давайте посмотрим, в каких исследовательских группах находится Феликс, и кто еще в этих группах.

START me = node:vertices('type:profile AND name:"Felix Eggers"')
MATCH me -[:member_of]-> group <-[:member_of]- other_profiles
RETURN DISTINCT other_profiles.name, COLLECT(DISTINCT group.name)
ORDER BY COUNT(*) DESC
LIMIT 5; 

Мы находим Джереми и Майкла в одной группе с Феликсом.

==> +-----------------------------------------------------------------------------+
==> | other_profiles.name | COLLECT(DISTINCT group.name)                          |
==> +-----------------------------------------------------------------------------+
==> | "Jeremy Chen"       | ["Conjoint Analysis and Discrete Choice Experiments"] |
==> | "Michael Waltinger" | ["Conjoint Analysis and Discrete Choice Experiments"] |
==> +-----------------------------------------------------------------------------+

Они в каких-либо других группах, которые могут помочь нам расширить сеть Феликса?

START me = node:vertices('type:profile AND name:"Felix Eggers"')
MATCH me -[:member_of]-> group <-[:member_of]- team_members 
         -[:member_of]-> other_group <-[:member_of]- other_profiles
RETURN DISTINCT other_profiles.name, COLLECT(DISTINCT other_group.name)
ORDER BY COUNT(*) DESC
LIMIT 5; 

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

START me = node:vertices('type:profile AND name:"Felix Eggers"')
MATCH me -[:member_of]-> group <-[:member_of]- team_members 
         -[:member_of]-> other_group <-[:member_of]- other_profiles
RETURN DISTINCT other_profiles.name, COUNT( DISTINCT other_group.name)
ORDER BY COUNT(*) DESC
LIMIT 5; 
==> +-----------------------------------------------------------+
==> | other_profiles.name   | COUNT( DISTINCT other_group.name) |
==> +-----------------------------------------------------------+
==> | "ABDUL SALAM YUSSIF"  | 12                                |
==> | "Nicholas Overton"    | 9                                 |
==> | "Ashley Cooke"        | 7                                 |
==> | "Joe Reevy"           | 6                                 |
==> | "Moeez Khademhoseiny" | 6                                 |
==> +-----------------------------------------------------------+

Соавторы:

START me = node:vertices('type:author AND name:"Felix Eggers"')
MATCH me <-[:authored_by]- publication -[:authored_by]-> co_authors 
RETURN DISTINCT co_authors.name; 

Эти люди являются соавторами публикации с Феликсом, поэтому им должно понравиться работать вместе и иметь схожие исследовательские интересы.

==> +--------------------------+
==> | co_authors.name          |
==> +--------------------------+
==> | "Victor Henning"         |
==> | "Thorsten Hennig-Thurau" |
==> | "Dominik Papies"         |
==> | "Fabian Eggers"          |
==> | "Henrik Sattler"         |
==> | "Mark B Houston"         |
==> | "Nils Wlömert"           |
==> +--------------------------+

Это не куча людей, давайте попробуем его соавторскую сеть 2-го уровня:

START me = node:vertices('type:author AND name:"Felix Eggers"')
MATCH me <-[:authored_by]- my_publications -[:authored_by]-> co_authors 
         <-[:authored_by]- their_publications -[:authored_by]-> their_co_authors
WHERE me <> their_co_authors 
  AND NOT(me <-[:authored_by]- my_publications -[:authored_by]-> their_co_authors)
RETURN DISTINCT their_co_authors.name, COUNT(*) AS cnt
ORDER BY cnt DESC
LIMIT 5; 

Мы исключаем Феликса и его соавторов из результата. Я нашел 18, но вот топ-5:

==> +-----------------------------+
==> | their_co_authors.name | cnt |
==> +-----------------------------+
==> | "Jan Reichelt"        | 27  |
==> | "Jason J Hoyt"        | 21  |
==> | "James Hammerton"     | 15  |
==> | "Kris Jack"           | 15  |
==> | "Dan Harvey"          | 15  |
==> +-----------------------------+

В том же Журнале:
мы также можем взглянуть на авторов, которые появились в том же Журнале, что и Феликс, так как Журналы, как правило, ориентированы на конкретные темы и курируют высококачественный контент.

START me = node:vertices('type:author AND name:"Felix Eggers"')
MATCH me <-[:authored_by]- my_publications -[:published_in]-> journal 
         <-[:published_in]- other_publications -[:authored_by]-> authors 
RETURN DISTINCT authors.name, COUNT(*) AS cnt
ORDER BY cnt DESC
LIMIT 5; 

Я нашел 35 авторов, которые были опубликованы в тех же журналах, но вот топ-5:

==> +--------------------------------+
==> | authors.name             | cnt |
==> +--------------------------------+
==> | "Thorsten Hennig-Thurau" | 7   |
==> | "Victor Henning"         | 4   |
==> | "Henrik Sattler"         | 4   |
==> | "Tillmann Wagner"        | 4   |
==> | "Richard J Lutz"         | 2   |
==> +--------------------------------+

Мы можем перейти на 2-й уровень здесь, используя его соавторов:

START me = node:vertices('type:author AND name:"Felix Eggers"')
MATCH me <-[:authored_by]- my_publications -[:authored_by]-> co_authors 
         <-[:authored_by]- their_publications -[:published_in]-> journal 
         <-[:published_in]- other_publications -[:authored_by]-> authors 
WHERE me <> authors 
  AND NOT(me <-[:authored_by]- my_publications -[:authored_by]-> authors)
RETURN DISTINCT authors.name, COUNT(*) AS cnt
ORDER BY cnt DESC
LIMIT 5; 

Этот запрос возвращает 19,5 тыс. Авторов, вот первые 5:

==> +-------------------------+
==> | authors.name      | cnt |
==> +-------------------------+
==> | "Thomas Cochrane" | 444 |
==> | "Amanda Peters"   | 360 |
==> | "David Jones"     | 336 |
==> | "DJ Riddell"      | 312 |
==> | "J Lavoué"        | 300 |
==> +-------------------------+

В этом списке представлены авторы, появившиеся в тех же журналах, что и его соавторы, упорядоченные по количеству существующих для них путей.

Интересуют те же дисциплины:

Мы действительно можем пойти несколькими путями здесь.

Из его профиля мы можем перейти к дисциплинам и найти другие профили, которые относятся к тем же дисциплинам.

START me = node:vertices('type:profile AND name:"Felix Eggers"')
MATCH me -[:interested_in]-> disciplines <-[:interested_in]- other_profiles
RETURN DISTINCT other_profiles.name, COLLECT(DISTINCT disciplines.name)
ORDER BY COUNT(*) DESC
LIMIT 5; 

Это вернет тонну людей, которые также входят в бизнес-администрирование, вот 5 из них:

==> +----------------------------------------------------------+
==> | other_profiles.name | COLLECT(DISTINCT disciplines.name) |
==> +----------------------------------------------------------+
==> | "John Smith"        | ["Business Administration"]        |
==> | "Andreas Müller"    | ["Business Administration"]        |
==> | "abc abc"           | ["Business Administration"]        |
==> | "abc def"           | ["Business Administration"]        |
==> | "Luis Farinha"      | ["Business Administration"]        |
==> +----------------------------------------------------------+

Поскольку мы знаем, что Феликс интересуется бизнес-администрированием, мы также можем перейти от дисциплин к публикациям, другим авторам, которые могут не иметь профиля в системе.

START me = node:vertices('type:discipline AND name:"Business Administration"')
MATCH me -[:by_discipline]- publications -[:authored_by]- author
RETURN author.name, COUNT(*) AS cnt
ORDER BY cnt DESC
LIMIT 5;
==> +---------------------------+
==> | author.name         | cnt |
==> +---------------------------+
==> | "Null Mancas Matei" | 11  |
==> | "Joanne Dyer"       | 8   |
==> | "Nicholas J Turro"  | 8   |
==> | "Steffen Jockusch"  | 4   |
==> | "Angel A Martí"     | 4   |
==> +---------------------------+

Во всяком случае, это было всего лишь исследование данных с Neo4j и Cypher . Я постараюсь создать сайт, который использует эти запросы до 31 августа. Оставьте комментарий, если у вас есть идеи или вы хотите помочь.