0

I have an user speaking several languages. I am writing a query to find out if the user speaks english. I want to find out if the user speaks english by searching if a relationship exists between the user node and and the language node. I am doing this using rels.to_other or rels.to_others. Both are failing as described below. And BTW what is the difference between the "to_other" and "to_others" methods?

irb(main):105:0> u
=> #<User uuid: "b1461edd-a574-44a7-9555-68659a361be2", created_at: Tue, 06 Oct 2015 16:21:26 +0000, name: "Levi Damian", type: "Regular", updated_at: Tue, 06 Oct 2015 16:21:26 +0000>

irb(main):106:0> l
=> #<Language uuid: "e388eb70-66b2-4b20-8f15-6ca11b34d03d", name: "English">

irb(main):107:0> u.rels.to_other(l)
 CYPHER 802ms MATCH n, (n)-[r]-(p) WHERE (ID(n) = {ID_n}) RETURN r as result | {:ID_n=>38}
NoMethodError:  CYPHER 125ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>38}
 CYPHER 125ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>43}
 CYPHER 125ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>38}
 CYPHER 124ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>42}
 CYPHER 128ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>38}
 CYPHER 130ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>41}
 CYPHER 124ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>38}
 CYPHER 125ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>86}
 CYPHER 124ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>38}
 CYPHER 129ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>87}
undefined method `to_other' for #<Array:0x007fedc2d6b980>
    from (irb):107
    from /Users/levi/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/railties-4.2.4/lib/rails/commands/console.rb:110:in `start'

Why this error and how I can make it work?

LDB
  • 692
  • 6
  • 18

1 Answers1

1

rels immediately returns all relationships from that node to... everything. It returns an array, hence the error. It can be an extremely slow, memory intensive operation if you have a node with many relationships.

Assuming you have a languages association in your model, you can do u.languages.match_to(l).exists? instead. It will return a boolean and does not return any graph objects. You can also use blank? or empty?.

subvertallchris
  • 5,282
  • 2
  • 25
  • 43
  • u.languages.match_to(l).exist? NoMethodError: undefined method `exist?' for # from /Users/levi/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/neo4j-5.2.9/lib/neo4j/active_node/query/query_proxy.rb:232:in `method_missing' – LDB Oct 09 '15 at 01:03
  • u.languages.match_to(l).count User#languages 778ms MATCH user0 WHERE (ID(user0) = {ID_user0}) MATCH user0-[rel1:`COMMUNICATING_IN`]->(result_languages:`Language`) WHERE (ID(result_languages) = {ID_result_languages}) RETURN count(result_languages) AS result_languages | {:ID_user0=>0, :ID_result_languages=>3} => 1 – LDB Oct 09 '15 at 01:18
  • It's `exists?`, with an s. I updated my answer to reflect this. – subvertallchris Oct 09 '15 at 14:04
  • This worked perfectly this time. However this is not returning all relationships the user has for each language he speaks. It returns true or false only if the user speaks or not a language. How I can retrieve if user (me) I am speaking also German and French? I should get an array of relationships pointing from use (me) to each language I am speaking, in my case 3 relationships. – LDB Oct 13 '15 at 16:10
  • That's a bit different. If you want to return all of the relationships, `u.languages.each_rel` or `u.languages(:l, :r).pluck(:r)` will do it. – subvertallchris Oct 13 '15 at 18:56