neo4j - вернуть единственный экземпляр узла - запрос по свойству? - PullRequest
0 голосов
/ 25 мая 2019

Я строю социальную сеть, в которой есть специализированная аудитория.

Пользователи связаны друг с другом тремя основными типами отношений.

[:FRIENDS]->(:USER), 
[:WORKS_AT]->(:COMPANY), 
[:WORKED_AT]->(:COMPANY), 
[:FOLLOWS]. 

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

Например, если пользователь хочет найти другого пользователя с именем «Барт Симпсон» - сначала мы проверим отношения между сотрудниками ([:WORKS_AT],[:WORKED_AT]). Этим отношениям я присвоил приоритет 1. Таким образом, «Барт Симпсон», который работает со мной, появится в результатах поиска до «Барт Симпсон», который живет за сотни миль в Спрингфилде.

Второй приоритет - [:FRIENDS]->(:USER). У кого-нибудь из моих друзей есть друг по имени "Барт Симпсон?" Приоритет № 2.

Последний приоритет - глобальный поиск. У меня нет коллег по имени «Барт Симпсон», у моих друзей нет друзей по имени «Барт Симпсон» - но я встретил Барта на конференции, и я хочу «подружиться» с ним. Итак, я добавил «Глобальный» поиск. Найти любых пользователей с именем "Барт Симпсон".

Пока что это мой Сайфер:

optional match (u:USER {id:'1'})-[:WORKS_AT|:WORKED_AT]-(w:COMPANY)-[r]-(f:USER)
with collect(f{.*, priority:1,relationship:r.title,type:type(r)}) as user
optional match (u:USER {id: '1'})-[:FRIENDS]-(:USER)-[r:FRIENDS]-(f:USER)
with user + collect(f{.*, priority:2,relationship:r.title,type:type(r)}) as user
optional match (f:USER)
where f.id <> '1'
with user + collect(f{.*, priority:3,relationship:'',type:''}) as user
unwind user as users 
with users as user
where toLower(user.last_name) STARTS WITH toLower('Sc') OR toLower(user.first_name) STARTS WITH toLower('Sc')
return distinct user

Это фантастика - однако пользователь может работать в той же компании, что и дружить, а также появляться в глобальном поиске. Итак, у нас есть потенциал для трех (или более) «копий» одного и того же пользователя - с разными атрибутами отношений. Атрибуты отношений важны, потому что в приложении они обеспечивают важный контекст для поиска. «Барт Симпсон - Работает в компании XYZ.»

Так что я действительно ищу возможность вернуть запись пользователя с наивысшим приоритетом - и сделать это на основе поля «ID». Если это не сработает, я могу увидеть ситуацию, когда мы пытаемся обновить свойство узла. Таким образом, когда запрос достигает поиска с приоритетом 2, если в коллекции уже есть пользователь с таким же «идентификатором», он просто добавляет тип отношения P2 к записи. Либо со мной все в порядке.

Я открыт для предложений и слушания!

1 Ответ

0 голосов
/ 26 мая 2019

Итак, я добился определенного прогресса!

MATCH 
    (subject:USER {id:'1'})
MATCH
    (subject)-[:WORKS_AT|:WORKED_AT]-(w:COMPANY)-[r]-(f1:USER)
WHERE 
    toLower(f1.last_name) STARTS WITH toLower('Sc') or 
    toLower(f1.first_name) STARTS WITH toLower('Sc')
WITH 
    COLLECT(f1.id) AS userIds, 
    COLLECT(f1{.*,priority:1,rType:type(r), title:r.title, detail:w.name}) AS users
OPTIONAL MATCH
    (subject)-[:FRIEND]-(fw:USER)-[r:FRIEND]-(f2:USER)
WHERE 
    NOT(f2.id in userIds) AND 
    (
        toLower(f2.last_name) STARTS WITH toLower('Sc') or 
        toLower(f2.first_name) STARTS WITH toLower('Sc')
    )
WITH 
    users + COLLECT(f2{.*,priority:2,rType:"FRIEND", title:"Friends with " + fw.first_name + " " + fw.last_name, detail:''}) AS users, 
    userIds + collect(f2.id) AS userIds
OPTIONAL MATCH
    (f3:USER)
WHERE 
    NOT(f3.id in userIds) AND 
    (
        toLower(f3.last_name) starts with toLower('Sc') OR 
        toLower(f3.first_name) starts with toLower('Sc')
    )
WITH 
    users + COLLECT(f3{.*,priority:3,rType:"GLOBAL", title:"", detail:''}) AS users
RETURN  
    users

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

Это работает - и сейчас я собираюсь бежать с этим. Это наиболее эффективный запрос или есть лучший способ справиться с этим сценарием?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...