-
Notifications
You must be signed in to change notification settings - Fork 276
Validation and Case Sensitivity in Neo4j.rb 3.0
ActiveNode and ActiveRel's validations are provided by ActiveModel::Validations
, so everything here or in your version of Rails should apply. There is one caveat when it comes to uniqueness and case-sensitivity, which has somewhat unique handling in Neo4j.
In Neo4j.rb, the preferred way of declaring a property unique is through a constraint, which is a type of database index that forces uniqueness. As described here, the proper syntax for this:
property :name, constraint: :unique
The reason for the different behavior is Neo4j does not support case-insensitive indexes or constraints. Behavior changes with different types of uniqueness validations:
This will result in an n+1 query involving a regex match:
validates_uniqueness_of :name
If you want it to be case-insensitive, you can do this:
validates_uniqueness_of :name, case_sensitive:false
...and it will modify the Cypher match to be case-insensitive.
And, at the moment, this appears to not work at all and will be investigated:
validate :name, unique: true
Related to this, you should also be aware searches are case-sensitive, so Band.where(name: 'Ulver')
and Band.where(name: 'ULVER')
will give different results. To perform a regex search, do Band.where(name: /ulver/i)
, but be aware that this will bypass your indexes and may have a performance impact.
An option to work around this is to declare a uniqueness constraint on a second, normalized property. This duplicates some data but will offer a performance benefit when your database is large enough. You should also remember that Neo4j compresses and symbolizes strings when possible, so this additional data may not have any noticeable impact on disk footprint. An implementation of that may look like this:
class Student
include Neo4j::ActiveNode
property :name
property :normalized_name, constraint: :unique
validates_presence_of :name
validate :set_normalized_name
private
def set_normalized_name
self.normalized_name = self.name.downcase if self.name
end
end
If the inability to use an index with a case-insensitive search bothers you and you'd rather not use this workaround, you can use the Searchkick gem to add Elasticsearch support to your app.
WARNING: Much of the information in this wiki is out of date. We are in the process of moving things to readthedocs
- Project Introduction
- Neo4j::ActiveNode
- Neo4j::ActiveRel
- Search and Scope
- Validation, Uniqueness, and Case Sensitivity
- Indexing VS Legacy Indexing
- Optimized Methods
- Inheritance
- Core: Nodes & Rels
- Introduction
- Persistence
- Find : Lucene
- Relationships
- Third Party Gems & extensions
- Scaffolding & Generators
- HA Cluster