If I understand you correctly, then you'd create the node upfront, and don't 
pass it to the code that creates the relationship but instead lookup the node 
using the index (or a relation from a e.g. type node).

If you want to create it on demand, just add an index lookup before creation.

Cheers

Michael

Am 18.02.2011 um 21:29 schrieb Mark Nijhof:

> Hi Michael,
> 
> A continuation :)
> 
> When I add a relation to a specific type node to indicate what type the node 
> represents then I need to make sure that this node is unique. So the question 
> is should I create the different type nodes before hand, or can I create them 
> on demand? And the concern is consistency, what happens when two requests 
> both want to create this unique type node? Is this possible, or can I guard 
> myself from this? Personally I like my app to create such a node on demand, 
> as this makes moving forward easier (no possibility to screw that up by 
> forgetting to add a type node).
> 
> -Mark
> 
> 
> On Fri, Feb 18, 2011 at 12:21 PM, Michael Hunger 
> <michael.hun...@neotechnology.com> wrote:
> Feel free to skim it or not, just don't want it to get lost so that no one 
> else can learn from that or contribute alternative solutions.
> 
> Cheers
> 
> Michael
> 
> 1) All nodes are equal in Neo4j if I am correct, so if I have different types 
> myself then I just create a node_type property with a text string to 
> differentiate between f.ex. users and jobs. Is this the correct way to handle 
> this?
> 
> 2) Complex data structures, I need to store complex data structures in Neo4j, 
> think about a whole CV like LinkedIn. When I create or update nodes can U 
> pass-in this complex data structure as a whole? F.ex. below here could I add 
> a parameter CV that contains a Hash where some values are Hashes themselves 
> again? Or can  should I use JSON as a value?
> Neography::Node.create("age" => 31, "name" => "Max")
> 
> 3) I am currently creating my own models (Rails based web app) where the 
> models themselves are not so much used like in Rails, they are only a nice 
> way to collect logic in one place. F.ex. I could have Employee.create_new 
> hash which internally will use neography to create a new employee and return 
> the created one as a hash. Is this a good way to thank about the problem, or 
> have other patterns emerged?
> 
> 1) There are several strategies, marking the nodes with certain properties is 
> one, others are - linking the nodes to a "category" node so that they can be 
> easily accessed from there, or putting them in a dedicated index for quick 
> lookup.
> 
> 2) Nodes only have primitive properties right now. To store hashes or more 
> complex document structures you use other nodes and relationships between 
> them. That should be quite easy to put in a helper method.
> i.e. if the inner property is a hash take its property name and instead of 
> making a property out of that one, create a relationship with this name to a 
> node which has the hash keys + values as properties (and recursively so).
> 
> Fortunately it is easy with ruby to just reopen the Node class and add those 
> convenience methods. I did that as well. (Code below)
> 
> 3) I create my own Domain objects for the Neo4j-Hosting Domain and just have 
> them get a Neography node as intitializer param, then you can delegate all 
> store-methods to this node or its node.neo_server and have the other domain 
> code directly in the object (code also below). I'm also in the process of 
> exploring this whole remote-rest-store domain modelling, so we can certainly 
> learn a lot from each other.
> 
> Mark you can still do  your uniqueness constraint of the email with the 
> index. I would have written the same as Jim, put the E-Mail addresses in a 
> string array field, but be sure to index them not as an array but 
> individually.
> 
> Regarding your other questions of reading structures. Traversing is crazy 
> fast in Neo4j. So what you do is not a manual navigation over the 
> relationships but:
> - you get your start node (i.e. the one being the person) from the index or 
> from another traversal. (you can see that node like a root entity).
> 
> Then you specify a traversal description. I.e. which relationships to 
> traverse, how deep etc. And then let the neo4j traverser do the work and have 
> you return all the paths to the nodes that are included in your traversal - 
> i.e. your whole document == aggregate structure.
> 
> Then in the client you pull those paths into your domain model and have it 
> ready for processing/displaying whatever.
> 
> For hints for the traversal either look at the code of the previous email or 
> that a quick look at the neo4j-imdb-app sourcecode at github: 
> https://github.com/jexp/heroku-neo4j-example
> 
> Cheers
> 
> Michael
> 
> Ok one more question for modeling the data: Say a user can have multiple 
> e-mail addresses what is the best way to model this? Have a single property 
> containing a list with addresses or let
> email_address be its own entity and create relations between the user and 
> e-mail_address? The email address will be used to search for a user f.ex. so 
> I rather have Neo4j being able to
> determine if it already exists.
> 
>  -Mark
> 
> 
> There's nothing in Neo4j that determines this one way or another. If email 
> addresses are first class citizens in your domain, then they should be nodes. 
> Otherwise make them properties.
> 
> For instane, if you want to be able to assert that two users are actually the 
> same person because they share an email address, then make the email address 
> a node. Otherwise it's a property.
> 
> Jim
> 
> I am using e-mail address as a way to select a user, but I didn't think of it 
> as a first class citizen. A user can have multiple e-mail addresses and in 
> cases non. The thing I am not sure
> about is how to select a user by e-mail address. Can Neo4j have an Array as 
> property type, using the ReST API and select a node if it the array contains 
> the filter value?
> 
> I am starting to realize that how I think about my data needs to be a bit 
> different from f.ex. MongoDB or CouchDB. In many ways I see great 
> possibilities, but need to get my head around
> these fundamental things :)
> 
> -Mark
> 
> 
> It's possible to index node properties, that gives you effectively what Mongo 
> does. Arrays are supported, you just pass in a JSON array:
> 
> { "email_addresses" : ["j...@webber.name", "j...@jimwebber.org", 
> "j...@neotechnology.com"]}
> 
> The question you need to answer is: is there any value in the relationship 
> between a user and their email address(es)?
> 
> Jim
> 
> Ah cool, that is what I was wondering about how easy Neo could index 
> properties like an array. Because this is a border case (I might actually 
> promote e-mail address to a first class citizen for uniqueness check), but 
> there are other cases where I do not see the need to do this. Then it is good 
> to know that Neo will handle that easily.
> 
> How much is the ReST API behind the direct Java way?
> 
> -Mark
> 
> Regarding the second - information about those concepts is distributed over 
> blog posts, wiki entries and mailing list posts. We certainly need more docs 
> from the users/developers point of
> view, e.g. on how to model your domain in a graph.
> 
> What I've just found (but that is by far not enough: 
> http://wiki.neo4j.org/content/Domain_Modeling_Gallery)
> 
> http://wiki.neo4j.org/content/Design_Guide
> http://stackoverflow.com/questions/1000162/has-anyone-used-graph-based-databases-http-neo4j-org
> 
> http://www.build47.com/posts/neo4j-presentation-at-twitter-headquaters/
> http://www.slideshare.net/directi/neo4j-and-the-benefits-of-graph-dbs-3-3325734
> 
> I also would like to discuss how one could map the DDD terms onto a graph 
> database and where it is fitting and where not.
> 
> Two last points: don't underestimate relationships, they are full first level 
> citizens and go for traversals rather than manually navigating along the 
> relationships.
> 
> node_ext.rb
> 
> require 'rubygems'
> require 'neography'
> 
> module Neography
>  class Node
>    class << self
>      def create_and_index(data, to_index)
>        node = Neography::Node.create(data)
>        return node unless to_index
>        to_index.each do |index,names|
>          names.each do | prop |
>            
> node.neo_server.add_node_to_index(index,prop,data[prop],node.neo_id)
>          end
>        end
>        node
>      end
> 
>      def find(index, prop, value)
>        res = Neography::Rest.new.get_node_index(index,prop,value)
>        return nil unless res
>        Neography::Node.load(res.first)
>      end
>    end
>  end
>  class Rest
>    def get_type(type)
>        case type
>          when :node, "nodes", :nodes, "nodes"
>            "node"
>          when :relationship, "relationship", :relationships, "relationships"
>            "relationship"
>          when :path, "path", :paths, "paths"
>            "path"
>          when :fullpath, "fullpath", :fullpaths, "fullpaths"
>            "fullpath"
>          else
>            "node"
>        end
>      end
>  end
> end
> 
> 
> domain.rb
> require 'node_ext'
> 
> # todo I want to be able to filter for properties with the REST api w/o 
> reverting to JS
> module Gateway
>  class Provider
>  def initialize(node)
>    @node = node
>  end
> 
>  def to_s
>    "#{@node.name} (#{@node.neo_id})"
>  end
> 
>  class << self
>    def get(name)
>      node = Neography::Node.find(:providers,:name,name)
>      return nil unless node
>      Provider.new(node)
>    end
> 
>    def add(name)
>       provider = Provider.get(name)
>       return provider if provider
>       node = Neography::Node.create_and_index({:name => name}, :providers => 
> [:name])
>       return nil unless node
>       Provider.new(node)
>    end
>  end
> 
>  def plans
>    @node.outgoing(:active_plan).collect
>  end
>  def plan(name)
>    plans.find { |plan| plan.name == name }
>  end
> 
>  def users
>    rels.incoming(:account).collect
>  end
>  def userFor(account)
>    users = @node.incoming(:account).filter(" position.lastRelationship() != 
> null && position.lastRelationship().getProperty('account') == '#{account}';")
>    return User.new(users.first) if users && !users.empty?
>    user = Neography::Node.create_and_index({:name => account, :email => 
> account}, :users => [:email, :name ])
>    @node.neo_server.create_relationship(:account, user, @node, {:account => 
> account })
>    User.new(user)
>  end
> 
>  def new_hash(size = 8)
>    Digest::SHA1.hexdigest(rand.to_s)[0..size]
>  end
> 
>  def databaseFor(user, plan)
>    begin
>      id = new_hash
>    end while !Node.find(:databases, :id, id)
>    db = Neography::Node.create_and_index({
>        :id => id, :login => new_hash, :password => new_hash,
>        :state => :creating
>    }, :databases => [:id])
> 
>    user.outgoing(:active_database) << db
>    db.outgoin(:has_plan) << plan
> 
>    Database.new(db)
>  end
> end
> end
> 
> 
> 
> 
> _______________________________________________
> Neo4j mailing list
> User@lists.neo4j.org
> https://lists.neo4j.org/mailman/listinfo/user
> 
> 
> 
> -- 
> Mark Nijhof
> m: 0047 95 00 99 37
> e:  mark.nij...@cre8ivethought.com
> b:  cre8ivethought.com/blog/index
> 
> 
> 
> "Walking on water and developing software from a specification are easy if 
> both are frozen."
> 
> -- Edward V Berard
> 
> 
> 

_______________________________________________
Neo4j mailing list
User@lists.neo4j.org
https://lists.neo4j.org/mailman/listinfo/user

Reply via email to