Giter Club home page Giter Club logo

neoid's Introduction

Neoid

Gem Version Code Climate Build Status

This gem is not stable. There are currently no stable versions. We're working on fixing this right now. Apologies.

Make your ActiveRecords stored and searchable on Neo4j graph database, in order to make fast graph queries that MySQL would crawl while doing them. Originally by @elado.

Neoid is to Neo4j as Sunspot is to Solr. You get the benefits of Neo4j's speed while keeping your schema on your RDBMS.

Neoid does not require JRuby. It's based on the Neography gem which uses Neo4j's REST API.

Neoid offers querying Neo4j for IDs of objects and then fetch them from your RDBMS, or storing all desired data on Neo4j.

Important: If you are hosting your application on Heroku with Neoid, GrapheneDB does support Gremlin code; their add-on is located here. Also be reminded that the Gremlin code is actively being refactored into Cypher.

Changelog

See Changelog. Including some breaking changes (and solutions) from previos versions.

Installation

Add to your Gemfile and run the bundle command to install it.

gem 'neoid'

Requires Ruby 1.9.3 or later and Neo4j 1.9.8.

Installing Neo4j 1.9.8 for your project

We're currently working to bump to 2.1.x land, but for now, you have to use 1.9.8. To get started, install neo4j locally in your project with:

gem install neo4j-core --pre
rake neo4j:install[community,1.9.8]
rake neo4j:start

Usage

Rails app configuration:

Initializer neography and neoid in an initializer that is prefixed with 01_, such as config/initializers/01_neo4j.rb:

ENV["NEO4J_URL"] ||= "http://localhost:7474"

uri = URI.parse(ENV["NEO4J_URL"])

$neo = Neography::Rest.new(uri.to_s)

Neography.configure do |c|
  c.server = uri.host
  c.port = uri.port

  if uri.user && uri.password
    c.authentication = 'basic'
    c.username = uri.user
    c.password = uri.password
  end
end

Neoid.db = $neo

Neoid.configure do |c|
  # should Neoid create sub-reference from the ref node (id#0) to every node-model? default: true
  c.enable_subrefs = true
end

ActiveRecord configuration

Nodes

For nodes, first include the Neoid::Node module in your model:

class User < ActiveRecord::Base
  include Neoid::Node
end

This will help to create/update/destroy a corresponding node on Neo4j when changed are made a User model.

Then, you can customize what fields will be saved on the node in Neo4j, inside neoidable configuration, using field. You can also pass blocks to save content that's not a real column:

class User < ActiveRecord::Base
  include Neoid::Node
  
  neoidable do |c|
    c.field :slug
    c.field :display_name
    c.field :display_name_length do
      self.display_name.length
    end
  end
end

Relationships

Let's assume that a User can Like Movies:

# user.rb

class User < ActiveRecord::Base
  include Neoid::Node

  has_many :likes
  has_many :movies, through: :likes

  neoidable do |c|
    c.field :slug
    c.field :display_name
  end
end


# movie.rb

class Movie < ActiveRecord::Base
  include Neoid::Node

  has_many :likes
  has_many :users, through: :likes

  neoidable do |c|
    c.field :slug
    c.field :name
  end
end


# like.rb

class Like < ActiveRecord::Base
  belongs_to :user
  belongs_to :movie
end

Now let's make the Like model a Neoid, by including the Neoid::Relationship module, and define the relationship (start & end nodes and relationship type) options with neoidable config and relationship method:

class Like < ActiveRecord::Base
  belongs_to :user
  belongs_to :movie

  include Neoid::Relationship

  neoidable do |c|
    c.relationship start_node: :user, end_node: :movie, type: :likes
  end
end

Neoid adds the methods neo_node and neo_relationships to instances of nodes and relationships, respectively.

So you could do:

user = User.create!(display_name: "elado")
user.movies << Movie.create("Memento")
user.movies << Movie.create("Inception")

user.neo_node                # => #<Neography::Node…>
user.neo_node.display_name   # => "elado"

rel = user.likes.first.neo_relationship
rel.start_node  # user.neo_node
rel.end_node    # user.movies.first.neo_node
rel.rel_type    # 'likes'

Disabling auto saving to Neo4j:

If you'd like to save nodes manually rather than after_save, use auto_index: false:

class User < ActiveRecord::Base
  include Neoid::Node
  
  neoidable auto_index: false do |c|
  end
end

user = User.create!(name: "Elad") # no node is created in Neo4j!

user.neo_save # now there is!

Querying

You can query with all Neography's API: traverse, execute_query for Cypher, and execute_script for Gremlin.

Basics:

Finding a node by ID

Nodes and relationships are auto indexed in the node_auto_index and relationship_auto_index indexes, where the key is Neoid::UNIQUE_ID_KEY (which is 'neoid_unique_id') and the value is a combination of the class name and model id, Movie:43, this value is accessible with model.neo_unique_id. So use the constant and this method, never rely on assebling those values on your own because they might change in the future.

That means, you can query like this:

Neoid.db.get_node_auto_index(Neoid::UNIQUE_ID_KEY, user.neo_unique_id)
# => returns a Neography hash

Neoid::Node.from_hash(Neoid.db.get_node_auto_index(Neoid::UNIQUE_ID_KEY, user.neo_unique_id))
# => returns a Neography::Node

Finding all nodes of type

If Subreferences are enabled, you can get the subref node and then get all attached nodes:

Neoid.ref_node.outgoing('users_subref').first.outgoing('users').to_a
# => this, according to Neography, returns an array of Neography::Node so no conversion is needed

Gremlin Example:

These examples query Neo4j using Gremlin for IDs of objects, and then fetches them from ActiveRecord with an in query.

Of course, you can store using the neoidable do |c| c.field ... end all the data you need in Neo4j and avoid querying ActiveRecord.

Most liked movies

gremlin_query = <<-GREMLIN
  m = [:]

  g.v(0)
    .out('movies_subref').out
      .inE('likes')
      .inV
      .groupCount(m).iterate()

  m.sort{-it.value}.collect{it.key.ar_id}
GREMLIN

movie_ids = Neoid.db.execute_script(gremlin_query)

Movie.where(id: movie_ids)

Side note: the resulted movies won't be sorted by like count because the RDBMS won't necessarily do it as we passed a list of IDs. You can sort it yourself with array manipulation, since you have the ids.

Movies of user friends that the user doesn't have

Let's assume we have another Friendship model which is a relationship with start/end nodes of user and type of friends,

user = User.find(1)

gremlin_query = <<-GREMLIN
  u = g.idx('node_auto_index').get(unique_id_key, user_unique_id).next()
  movies = []

  u
    .out('likes').aggregate(movies).back(2)
    .out('friends').out('likes')
    .dedup
    .except(movies).collect{it.ar_id}
GREMLIN

movie_ids = Neoid.db.execute_script(gremlin_query, unique_id_key: Neoid::UNIQUE_ID_KEY, user_unique_id: user.neo_unique_id)

Movie.where(id: movie_ids)

Full Text Search

Index for Full-Text Search

Using search block inside a neoidable block, you can store certain fields.

# movie.rb

class Movie < ActiveRecord::Base
  include Neoid::Node

  neoidable do |c|
    c.field :slug
    c.field :name

    c.search do |s|
      # full-text index fields
      s.fulltext :name
      s.fulltext :description

      # just index for exact matches
      s.index :year
    end
  end
end

Records will be automatically indexed when inserted or updated.

Querying a Full-Text Search index

# will match all movies with full-text match for name/description. returns ActiveRecord instanced
Movie.neo_search("*hello*").results

# same as above but returns hashes with the values that were indexed on Neo4j
Movie.search("*hello*").hits

# search in multiple types
Neoid.neo_search([Movie, User], "hello")

# search with exact matches (pass a hash of field/value)
Movie.neo_search(year: 2013).results

Full text search with Neoid is very limited and is likely not to develop more than this basic functionality. I strongly recommend using gems like Sunspot over Solr.

Batches

Neoid has a batch ability, that is good for mass updateing/inserting of nodes/relationships. It sends batched requests to Neography, and takes care of type conversion (neography batch returns hashes and other primitive types) and "after" actions (via promises).

A few examples, easy to complex:

Neoid.batch(batch_size: 100) do
  User.all.each(&:neo_save)
end

With then:

User.first.name # => "Elad"

Neoid.batch(batch_size: 100) do
  User.all.each(&:neo_save)
end.then do |results|
  # results is an array of the script results from neo4j REST.

  results[0].name # => "Elad"
end

Nodes and relationships in the results are automatically converted to Neography::Node and Neography::Relationship, respectively.

With individual then as well as then for the entire batch:

Neoid.batch(batch_size: 30) do |batch|
  (1..90).each do |i|
    (batch << [:create_node, { name: "Hello #{i}" }]).then { |result| puts result.name }
  end
end.then do |results|
  puts results.collect(&:name)
end

When in a batch, neo_save adds gremlin scripts to a batch, instead of running them immediately. The batch flushes whenever the batch_size option is met. So even if you have 20000 users, Neoid will insert/update in smaller batches. Default batch_size is 200.

Inserting records of existing app

If you have an existing database and just want to integrate Neoid, configure the neoidables and run in a rake task or console.

Use batches! It's free, and much faster. Also, you should use includes to incude the relationship edges on relationship entities, so it doesn't query the DB on each relationship.

Neoid.batch do
  [ Like.includes(:user).includes(:movie), OtherRelationshipModel.includes(:from_model).includes(:to_model) ].each { |model| model.all.each(&:neo_save) }

  NodeModel.all.each(&:neo_save)
end

This will loop through all of your relationship records and generate the two edge nodes along with a relationship (eager loading for better performance). The second line is for nodes without relationships.

For large data sets use pagination. Better interface for that in the future.

Behind The Scenes

Whenever the neo_node on nodes or neo_relationship on relationships is called, Neoid checks if there's a corresponding node/relationship in Neo4j (with the auto indexes). If not, it does the following:

For Nodes:

  1. Ensures there's a sub reference node (read here about sub references), if that option is on.
  2. Creates a node based on the ActiveRecord, with the id attribute and all other attributes from neoidable's field list
  3. Creates a relationship between the sub reference node and the newly created node
  4. Auto indexes a node in the auto index, for fast lookup in the future

Then, when it needs to find it again, it just seeks the auto index with that ActiveRecord id.

For Relationships:

Like Nodes, it uses an auto index, to look up a relationship by ActiveRecord id

  1. With the options passed in the neoidable, it fetches the start_node and end_node
  2. Then, it calls neo_node on both, in order to create the Neo4j nodes if they're not created yet, and creates the relationship with the type from the options.
  3. Adds the relationship to the relationship index.

Testing

In order to test your app or this gem, you need a running Neo4j database, dedicated to tests.

I use port 7574 for testing.

To run another database locally (read here too):

Copy the entire Neo4j database folder to a different location,

or

symlink bin, lib, plugins, system, copy conf to a single folder, and create an empty data folder.

Then, edit conf/neo4j-server.properties and set the port (org.neo4j.server.webserver.port) from 7474 to 7574 and run the server with bin/neo4j start

Testing Your App with Neoid (RSpec)

In environments/test.rb, add:

ENV["NEO4J_URL"] = 'http://localhost:7574'

In your spec_helper.rb, add the following configurations:

config.before :all do
  Neoid.clean_db(:yes_i_am_sure)
end

config.before :each do
  Neoid.reset_cached_variables
end

Testing This Gem

Run the Neo4j DB on port 7474, and run rake from the gem folder.

Contributing

Please create a new issue if you run into any bugs. Contribute patches via pull requests. Write tests and make sure all tests pass.

TO DO

TO DO


Developed by @elado and @BenMorganIO

neoid's People

Contributors

benmorganio avatar elado avatar minsikzzang avatar mockdeep avatar nelsonwittwer avatar rubinsh avatar snappedtogrid avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

neoid's Issues

Delete relationship issue

I am experimenting with neo4j 1.6 using neoid.

I have created a simple User (node) + Follows (relationship) model (I mean who doesn't :))

When I create a relationship between two User entities I see the relationship appear in neo4j and in my RBDMS (postgresql), however when I delete that relationship I am not seeing the relationship be removed in neo4j even though it has been removed from the RBDMS.

I checked the ActiveRecord after_destroy callback tree and I can see the neo_destroy method is there.

I am updating my relationships using the following

user.friends = (user.friends - old_ids)        
user.friends = (user.friends + new_ids)         
user.save

so I am not calling .destroy directly but would assume it was implicit

database.yml

What kind of database.yml file should I have for neoid? Neoid uses ActiveRecord, and AR requires valid database.yml, but I couldn't find any info on how to configure it. I'm using only Neo4j in my app.

Non-model backed relationships

I am trying to create a relationship that is not backed by an active record relationship and wondered if this is supported in some way. Specifically what I am trying to do is have a relationship between a user and the board they created

class Board < ActiveRecord::Base
  belongs_to :user

  include Neoid::Node
  neoidable do |c|
    c.field :title
    c.field :created_at
  end

  include Neoid::Relationship
  neoidable do |c|
    c.relationship start_node: :user, end_node: :board, type: :created_board
    c.field :created_at
  end

  def board
    self
  end
end

class User < ActiveRecord::Base
  has_many :boards
end

It doesn't error out, but it also just hangs when I try and backfill data with neo_save

RuntimeError on neo_save(): "Accessed result too soon"

When calling neo_save() on a model in a Resque asynchronous job, I frequently get this error:

RuntimeError
Accessed result too soon
/var/www/srv/webdoc/shared/bundle/ruby/1.9.1/gems/neoid-0.1.2/lib/neoid/batch.rb:149:in `result'
/var/www/srv/webdoc/shared/bundle/ruby/1.9.1/gems/neoid-0.1.2/lib/neoid/batch.rb:154:in `method_missing'
/var/www/srv/webdoc/shared/bundle/ruby/1.9.1/gems/neoid-0.1.2/lib/neoid/node.rb:127:in `_neo_save'
/var/www/srv/webdoc/shared/bundle/ruby/1.9.1/gems/neoid-0.1.2/lib/neoid/model_additions.rb:56:in `neo_save'

I can not reproduce this issue when synchronously saving the model using Rails console.

Any idea where it may come from?

Heroku support

Wondering if you have any thoughts regarding replacing the gremlin parts of Neoid with the equivalent non-gremlin Neography calls. It seems like this should be possible, but I don't know if there might be reasons (performance?) not to do so.

Question about the generated graph

Hi, I'm taking a look at my graph and i'm not sure if it's a neo4j issue, or a neoid, but I have multiple sub ref nodes (repos in this case).

neo4j-sh (0)$ ls
==> (me)-[:tags_subref]->(tags_subref,8)
==> (me)-[:users_subref]->(users_subref,6)
==> (me)-[:repos_subref]->(repos_subref,5)
==> (me)-[:repos_subref]->(repos_subref,4)
==> (me)-[:repos_subref]->(repos_subref,3)
==> (me)-[:bookmarks_subref]->(bookmarks_subref,1)

I can post a copy of my graph if it helps, or is this perfectly normal?

Error coming from Neography when trying to save a category

I have this model set up exactly like my others but am getting the following error. Is it possible that this is some kind of reserved word in Neography?

Category.all.map{|c| c.neo_save}                                                                                                                                                                                                                                                                               
  Category Load (0.2ms)  SELECT `categories`.* FROM `categories` 
Neography::BadInputException: javax.script.ScriptException: java.lang.NullPointerException: Cannot invoke method put() on null object
from /Users/grockit/workspace/learnist/vendor/ruby/1.9.1/gems/neography-1.0.3/lib/neography/connection.rb:120:in `handle_4xx_500_response'

Here is the code

class Category < ActiveRecord::Base  
  include Neoid::Node

  neoidable do |c|
    c.field :name
    c.field :created_at
  end
end

Example of a self referential relationship

Hi,

I was wondering what would be the best way to define a self referential relationship neoid, for example:

class User
  has_many :follows
  has_many :followed_users, through: :follows
end

class Follow < ActiveRecord::Base
  belongs_to :user  
  belongs_to :followed_user, :class_name => 'User'  
end

Specs don't pass when enable_per_model_indexes = true

Hi,

We're trying to integrate neoid with per index models set on.
The problem is that now we can't create any activerecord model which includes neoid.

I also cloned the gem and set per model indexes to true on the spec_helper and the gem's specs don't pass.

Is there an easy way to fix this?

Thanks in advance.

Neoid with Neo4j 2.0.0-RC1 Gremlin Plugin Missing

With Neo4j version 2 the Gremlin Plugin isn't installed initially anmore.
See: https://groups.google.com/forum/#!searchin/neo4j/gremlinplugin/neo4j/aaxly1mH2Q4/MKJqjtTu2nwJ

Therefore, we have to add it manually.
Could you add one or two line to the README.MD to reflect these changes.
It would have saved me some time ;-)

Neography answers with 'No such ServerPlugin: "GremplinPlugin"'
when executing in neoid.rb:113
value = Neoid.db.execute_script(gremlin_query, script_vars)

You can find it here:
https://github.com/neo4j-contrib/gremlin-plugin

Error when trying to find a node

Code:

desc "Generate the Neo4j database of counties"
task :generate_adjacent_counties_database do
  file = File.open('db/adjacent_counties.txt')

  data = file.read.force_encoding("iso-8859-1").split("\n\n\n")

  data.each do |string|
    parent_node = nil
    string.each_line do |line|
      county = line.scan(/\[\[(.*), (.*)\]\]/)
      parent_node = Neography::Node.find("counties", "name", county[0][0])
      if parent_node.nil?
        parent_node = Neography::Node.create("name" => county[0][0], "state" => county[0][1])
      end
    end
  end
end

I'm trying to create a rake task to generate a database based on a text file, here's the error I'm getting:

Chintan at mbp in ~/Documents/Work/Aidin on feature/49442033_generate_database_of_adjacent_counties!
± rake generate_adjacent_counties_database
rake aborted!
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@aidin/gems/neography-1.0.9/lib/neography/connection.rb:140:in `handle_4xx_500_response'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@aidin/gems/neography-1.0.9/lib/neography/connection.rb:112:in `evaluate_response'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@aidin/gems/neography-1.0.9/lib/neography/connection.rb:37:in `get'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@aidin/gems/neography-1.0.9/lib/neography/rest/indexes.rb:65:in `find_by_key_value'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@aidin/gems/neography-1.0.9/lib/neography/rest/indexes.rb:56:in `find'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@aidin/gems/neography-1.0.9/lib/neography/rest.rb:209:in `find_node_index'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@aidin/gems/neography-1.0.9/lib/neography/index.rb:30:in `find'
/Users/Chintan/Documents/Work/Aidin/lib/tasks/generate_adjacent_counties_database.rake:18:in `block (3 levels) in <top (required)>'
/Users/Chintan/Documents/Work/Aidin/lib/tasks/generate_adjacent_counties_database.rake:16:in `each_line'
/Users/Chintan/Documents/Work/Aidin/lib/tasks/generate_adjacent_counties_database.rake:16:in `block (2 levels) in <top (required)>'
/Users/Chintan/Documents/Work/Aidin/lib/tasks/generate_adjacent_counties_database.rake:14:in `each'
/Users/Chintan/Documents/Work/Aidin/lib/tasks/generate_adjacent_counties_database.rake:14:in `block in <top (required)>'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-10.0.4/lib/rake/task.rb:246:in `call'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-10.0.4/lib/rake/task.rb:246:in `block in execute'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-10.0.4/lib/rake/task.rb:241:in `each'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-10.0.4/lib/rake/task.rb:241:in `execute'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-10.0.4/lib/rake/task.rb:184:in `block in invoke_with_call_chain'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-10.0.4/lib/rake/task.rb:177:in `invoke_with_call_chain'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-10.0.4/lib/rake/task.rb:170:in `invoke'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-10.0.4/lib/rake/application.rb:143:in `invoke_task'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-10.0.4/lib/rake/application.rb:101:in `block (2 levels) in top_level'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-10.0.4/lib/rake/application.rb:101:in `each'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-10.0.4/lib/rake/application.rb:101:in `block in top_level'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-10.0.4/lib/rake/application.rb:110:in `run_with_threads'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-10.0.4/lib/rake/application.rb:95:in `top_level'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-10.0.4/lib/rake/application.rb:73:in `block in run'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-10.0.4/lib/rake/application.rb:160:in `standard_exception_handling'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-10.0.4/lib/rake/application.rb:70:in `run'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@aidin/bin/ruby_noexec_wrapper:14:in `eval'
/Users/Chintan/.rvm/gems/ruby-1.9.3-p327@aidin/bin/ruby_noexec_wrapper:14:in `<main>'
Tasks: TOP => generate_adjacent_counties_database
(See full trace by running task with --trace)

Any ideas?

Belongs_to relationship

Does the gem currently support relationships other than ones that have a join model? The example code only shows this case. What if you have a 1 to many relationship instead of many to many. My current attempts to get this to work have failed

Relationship attributes

Sorry if this is covered somewhere but I could not find it. Is there a way to define an atribute on relations? created_at would be incredible useful for me and I can't figure out how to get it in there.

Adding properties to relationship

Really appreciating this software. Thank you.
Documentation is a little unclear about how to set properties on the neo4j relationships. I've been able to set properties on the active record side, but those properties don't seem to propagate to the neo4j object. Source code diving hasn't helped me yet (due to my own inadequacies).

neoidable error

Given that I have model as so:

class Post < ActiveRecord::Base
  include Neoid::Node
end

And in the console I run:

Post.create({title: "This and that", body: "hey there, this is the body!"})

It succeeds. But, if I do:

class Post < ActiveRecord::Base
  include Neoid::Node

  neoidable do |c|
    c.field :title
  end
end

Then this is what happens:

Post.create({title: "This and that", body: "hey there, this is the body!"})
NoMethodError: undefined method `dump' for #<Excon::Response:0x007ff3ad6f4228>
from /Users/benmorgan/.rvm/gems/ruby-2.1.2/gems/neography-1.5.1/lib/neography/connection.rb:216:in `handle_4xx_500_response'

I cannot figure this one out and I don't believe its happening in neography as its just the REST API wrapper. Any thoughts?

0.0.51 to 0.1.2 self-referential relationship breaks

When I upgraded I began experiencing an issue with a self-referential relationship where in the relationship in my Postgres database would appear, but would not in Neo4j.

class User < ActiveRecord::Base
  has_secure_password
  attr_accessible :bio, :email, :first_name, :last_name, :password, :password_confirmation

  include Neoid::Node
  has_many :follows
  has_many :reverse_follows, foreign_key: :following_id, class_name: "Follow"
  has_many :followers, through: :reverse_follows, source: :user
  has_many :followings, through: :follows
end

class Follow < ActiveRecord::Base
  include Neoid::Relationship
  attr_accessible :user_id, :following_id
  belongs_to :following, class_name: "User"
  belongs_to :user

  neoidable do |c|
    c.relationship start_node: :user, end_node: :following, type: :follows
  end
end

To recreate:

  1. create a user1 and a user2
  2. user1.followings << user2
  3. save user1
  4. user2.followings << user1
  5. save user2

In 0.0.51 this behaves as expected:
Screen Shot 2013-01-15 at 12 12 35 PM

In 0.1.2 only one relationship is created:
Screen Shot 2013-01-15 at 12 25 20 PM

I've tried it with per model indexing both on and off, just to be sure, with the same result. Is there some other change I'm missing?

Also; this might not be the appropriate place for this, but thanks a million for your work elado.

destroy callback with neoidable auto_index: false

It seems that Neoid is managing my neo4j records well when I use it without auto_index: false, including the Neo4j equivalent of INSERT, UPDATE, and DELETE.

For the one model where I have auto_index: false, it doesn't automatically INSERT, which is as I would expect.

Does this mean that it also does not automatically UPDATE and DELETE?

It appears that this is the case, thus I am left with a quandry. When the model with auto_index: false is deleted how do I also delete the record from Neo4j?

Make neoidable conditional?

I am interested in having the neoidable configuration be conditional, so that for example a node is only created/updated/deleted given some condition on a model field. I'd be happy to give it a whirl at some point if this makes sense.

Neoid main spec dependency

The neoid_spec.rb appears to fail when run by itself.

rspec spec/neoid_spec.rb throws:

Failure/Error: klass.instance_variable_get(:@neo_subref_node).should_not be_nil
       expected: not nil
            got: nil

Neoid error

I got neoid running on development but I'm getting errors running it against an EC2 neo4j from Heroku

The strange thing is that when I tried inserting nodes directly from neography - it worked :

@neo = Neography::Rest.new
node1 = @neo.create_node("age" => 31, "name" => "Max1") <- Successfully created a node

but

Profile.create

raised this error:
https://gist.github.com/827c9c170421aedb4360

I got the same error when trying to create a profile on EC2 server from my local machine

FATAL app unable to boot: Neoid 0.1.2 & Neography 0.9.10 (or master/HEAD)

FYI: @maxdemarzi @elado

I had neography as a git dependency in my gemfile. When I updated it recently neoid stopped working.

Compatible with Neoid

Not Compatible with Neoid

Using maxdemarzi/neography@aa6c1ae

neoid-0.1.2/lib/neoid/batch.rb:89:in `block in flush_batch': undefined method `collect' for #<String:0x00000006167c30> (NoMethodError)

Here's the longer trace:

2013-04-17T03:19:02.646896+00:00 app[web.1]: /app/vendor/bundle/ruby/1.9.1/gems/neoid-0.1.2/lib/neoid/batch.rb:89:in `block in flush_batch': undefined method `collect' for #<String:0x00000006167c30> (NoMethodError)
2013-04-17T03:19:02.646896+00:00 app[web.1]:    from /app/vendor/ruby-1.9.3/lib/ruby/1.9.1/benchmark.rb:280:in `measure'
2013-04-17T03:19:02.646896+00:00 app[web.1]:    from /app/vendor/bundle/ruby/1.9.1/gems/neoid-0.1.2/lib/neoid/batch.rb:88:in `flush_batch'
2013-04-17T03:19:02.646896+00:00 app[web.1]:    from /app/vendor/bundle/ruby/1.9.1/gems/neoid-0.1.2/lib/neoid/batch.rb:76:in `run'
2013-04-17T03:19:02.646896+00:00 app[web.1]:    from /app/vendor/bundle/ruby/1.9.1/gems/neoid-0.1.2/lib/neoid.rb:69:in `batch'
2013-04-17T03:19:02.646896+00:00 app[web.1]:    from /app/vendor/bundle/ruby/1.9.1/gems/neoid-0.1.2/lib/neoid.rb:218:in `initialize_subrefs'
2013-04-17T03:19:02.646896+00:00 app[web.1]:    from /app/vendor/bundle/ruby/1.9.1/gems/neoid-0.1.2/lib/neoid.rb:59:in `initialize_server'
2013-04-17T03:19:02.646896+00:00 app[web.1]:    from /app/vendor/bundle/ruby/1.9.1/gems/neoid-0.1.2/lib/neoid.rb:54:in `initialize_all'
2013-04-17T03:19:02.646896+00:00 app[web.1]:    from /app/vendor/bundle/ruby/1.9.1/gems/neoid-0.1.2/lib/neoid/railtie.rb:7:in `block (2 levels) in <class:Railtie>'

Adding the specific ref to my gemfile fixed it:

gem 'neography', github: 'maxdemarzi/neography', ref: 'e0f56c3900f9ef8b0b0134efcdc0c39209343f03'

Error with method 'neo_id'

I have a project in Ruby 2.2.4 with Rails 4.1.2 in which want to implement a new feature to allow users to connect with other users, so I will keep my database in Postgress (using ActiveRecords) with Neoid. I followed all the steps of https://github.com/neoid-gem/neoid documentation, but when I try to save a user has returned the following error:

NoMethodError (undefined method `neo_id 'for # <Hash: 0x0000000a4542a0>)

I have created a new project to analyze if my setup of Neo4j was not the problem, by following this tutorial: https://www.sitepoint.com/using-a-graph-database-with-ruby-part-ii-integration/ and the error did not appear. I tried with another with another class in my project and apparently worked well, which leads me to believe that the problem is something specific in User class. Here the parts involved code:

class User < ActiveRecord::Base 
  devise :database_authenticatable, :registerable, :confirmable,
         :recoverable, :rememberable, :trackable, :validatable, :omniauthable

  include Entity
  include Neoid::Node

  extend FriendlyId

  friendly_id :full_name, use: :slugged

  extend Enumerize
  extend ActiveModel::Naming

  neoidable do |c|
    c.field :slug
  end
  [...]
end

class Connection < ActiveRecord::Base

  include Neoid::Relationship

  belongs_to :user
  belongs_to :connected, class_name: User

  neoidable do |c|
    c.relationship start_node: :user, end_node: :connected, type: :connection
  end
end

class CreateConnections < ActiveRecord::Migration
  def change
    create_table :connections do |t|
      t.integer :user_id
      t.integer :connected_id
      t.timestamps
    end
  end
end

The question is, has anyone ever had a problem like this? Or have some feature in the User class that may be causing this error (like Devise, Enumerize ...)?

Already tried:

  • Reset the Postgress database;
  • Use neo_save on the users, but the error does not allow this action. Like "Inserting records of existing app" on documentation;
  • Check if the user is valid When I try to save;
  • Disabling auto saving to Neo4j;

getting error Neography::NeographyError: NeographyError: when i am using ActiveRecord with neo4j

hariprasad@Hari:~/Neo4J_Apps/sixth$ rails c
Running via Spring preloader in process 6236
Loading development environment (Rails 4.2.3)
2.3.0 :001 > Book.create(title:"haripr")
(0.1ms) begin transaction
SQL (0.3ms) INSERT INTO "books" ("title", "created_at", "updated_at") VALUES (?, ?, ?) [["title", "haripr"], ["created_at", "2017-08-04 14:07:54.288748"], ["updated_at", "2017-08-04 14:07:54.288748"]]
(0.1ms) rollback transaction
Neography::NeographyError: NeographyError:
--message: No such ServerPlugin: "GremlinPlugin",
--code: 404,
--stacktrace: ,
--request: {:path=>"/db/data/ext/GremlinPlugin/graphdb/execute_script", :body=>"{"script":" q = g.v(0).out(neo_subref_rel_type);\n\n subref = q.hasNext() ? q.next() : null;\n\n if (!subref) {\n subref = g.addVertex([name: neo_subref_rel_type, type: name]);\n g.addEdge(g.v(0), subref, neo_subref_rel_type);\n }\n\n subref\n","params":{"neo_subref_rel_type":"books_subref","name":"Book"}}"},
--index: 0
from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/neography-1.8.0/lib/neography/connection.rb:250:in raise_errors' from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/neography-1.8.0/lib/neography/connection.rb:222:in handle_4xx_500_response'
from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/neography-1.8.0/lib/neography/connection.rb:193:in return_result' from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/neography-1.8.0/lib/neography/connection.rb:164:in evaluate_response'
from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/neography-1.8.0/lib/neography/connection.rb:76:in block (3 levels) in <class:Connection>' from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/neography-1.8.0/lib/neography/connection.rb:89:in log'
from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/neography-1.8.0/lib/neography/connection.rb:67:in block (2 levels) in <class:Connection>' from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/neography-1.8.0/lib/neography/rest/gremlin.rb:14:in execute_script'
from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/neoid-0.2.1/lib/neoid.rb:122:in execute_script_or_add_to_batch' from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/neoid-0.2.1/lib/neoid/node.rb:73:in neo_subref_node'
from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/neoid-0.2.1/lib/neoid/node.rb:134:in _neo_save' from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/neoid-0.2.1/lib/neoid/model_additions.rb:56:in neo_save'
from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/neoid-0.2.1/lib/neoid/model_additions.rb:50:in neo_save_after_model_save' from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:430:in block in make_lambda'
from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:226:in block in halting_and_conditional' from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:504:in block in call'
... 20 levels...
from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/railties-4.2.3/lib/rails/commands/console.rb:9:in start' from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/railties-4.2.3/lib/rails/commands/commands_tasks.rb:68:in console'
from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/railties-4.2.3/lib/rails/commands/commands_tasks.rb:39:in run_command!' from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/railties-4.2.3/lib/rails/commands.rb:17:in <top (required)>'
from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:274:in require' from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:274:in block in require'
from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:240:in load_dependency' from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:274:in require'
from /home/hariprasad/Neo4J_Apps/sixth/bin/rails:9:in <top (required)>' from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:268:in load'
from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:268:in block in load' from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:240:in load_dependency'
from /home/hariprasad/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:268:in load' from /usr/share/rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in require'
from /usr/share/rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in require' from -e:1:in

'2.3.0 :002 >

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.