Estou tentando criar uma consulta usando uma cifra que "encontrará" ingredientes ausentes que um chef pode ter. Meu gráfico está configurado assim:
(ingredient_value)-[:is_part_of]->(ingredient)
(ingredient)
teria uma chave / valor de name = "dye colors". (ingredient_value)
poderia ter uma chave / valor de valor = "vermelho" e "faz parte de" o (ingredient, name="dye colors")
.
(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)
Estou usando essa consulta para obter todos os ingredients
, mas não seus valores reais, que uma receita exige, mas gostaria de retornar apenas o ingredients
que o chef não tem, em vez de todos os ingredientes que cada receita exige. eu tentei
(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)<-[:has_ingredient*0..0]-chef
mas isso não retornou nada.
Isso é algo que pode ser realizado por cypher / neo4j ou é algo que é melhor tratado devolvendo todos os ingredientes e separando-os eu mesmo?
Bônus: também existe uma maneira de usar cifragem para combinar todos os valores que um chef possui com todos os valores que uma receita exige. Até agora, retornei apenas todas as correspondências parciais retornadas por a chef-[:has_value]->ingredient_value<-[:requires_value]-recipe
e agregando os resultados sozinho.
exists
em umaWHERE
cláusula (também negá-la), neo4j.com/developer/subqueries/#existential-subqueries para obter mais informações.Respostas:
Atualização 01/10/2013:
Descobri isso na referência do Neo4j 2.0 :
Tente não usar relacionamentos opcionais. Sobre tudo,
não os use assim:
MATCH a-[r?:LOVES]->() WHERE r IS NULL
onde você apenas garante que eles não existam.Em vez disso, faça assim:
Usando cifragem para verificar se não existe relação:
O ? marca torna o relacionamento opcional.
OU
Em neo4j 2 faça:
Agora você pode verificar se há relacionamento não existente (nulo).
fonte
MATCH a...
exemplo agora deve serMATCH (a) WHERE NOT (a)-[:LOVES]->()
Para buscar nós sem nenhum relacionamento
Esta é a boa opção para verificar se o relacionamento existe ou não
Você também pode verificar várias condições para isso. Ele retornará todos os nós, que não tenham o relacionamento "reproduzido" ou "não reproduzido".
Para buscar nós que não têm nenhum relacionamento
Ele verificará se o nó não tem nenhum relacionamento de entrada / saída.
fonte
MATCH (player) WHERE NOT (player)-[r]-() RETURN player
dá um erro Variável r não definida . Como posso definir r?(player -[:rel]- ()
) ou deixe em branco para qualquer relação(player -[]- ()
MATCH (player) WHERE NOT (player)-[]-() RETURN player
- Funciona bemSe você precisar da semântica de "exclusão condicional", poderá fazer isso desta forma.
A partir do neo4j 2.2.1, você pode usar a
OPTIONAL MATCH
cláusula e filtrar osNULL
nós não correspondidos ( ).Também é importante usar
WITH
cláusula entre as cláusulasOPTIONAL MATCH
eWHERE
, de modo que a primeiraWHERE
defina uma condição para a correspondência opcional e a segundaWHERE
se comporte como um filtro.Supondo que temos 2 tipos de nós:
Person
eCommunication
. Se eu quiser obter todas as Pessoas que nunca se comunicaram por telefone, mas podem ter se comunicado de outras formas, eu faria esta consulta:O padrão de correspondência corresponderá a todas as Pessoas com suas comunicações, onde
c
seráNULL
para comunicações não telefônicas. Então, o filtro (WHERE
depoisWITH
) filtrará as comunicações telefônicas, deixando todas as outras.Referências:
http://neo4j.com/docs/stable/query-optional-match.html#_introduction_3 http://java.dzone.com/articles/new-neo4j-optional
fonte
Eu escrevi um resumo mostrando como isso pode ser feito naturalmente usando Cypher 2.0
http://gist.neo4j.org/?9171581
O ponto principal é usar a correspondência opcional para ingredientes disponíveis e, em seguida, comparar para filtrar os ingredientes ausentes (nulos) ou ingredientes com o valor errado.
Observe que a noção é declarativa e não precisa descrever um algoritmo, você apenas anota o que precisa.
fonte
Concluí esta tarefa usando gremlin. eu fiz
Isso retornou os caminhos de todos os ingredientes que faltavam. Não fui capaz de formular isso na linguagem cifrada, pelo menos para a versão 1.7.
fonte
A última consulta deve ser:
Esse padrão:
(ingredient)<-[:has_ingredient*0..0]-chef
É a razão pela qual não retornou nada.
*0..0
significa que o comprimento dos relacionamentos deve ser zero, o que significa que ingrediente e chef devem ser o mesmo nó, o que não é verdade.fonte