I have a Neo4j/OGM Entity Person which I mapped to the Label User using
#NodeEntity(label="User).
I now want to write a custom Query MATCH (p:Person) where....
As far as I see, there is no way to use my Application-Side Type Person instead of the Graph-Side Label User like in Hibernate, right?
If there is a way, please explain how to do this, or tell my a key-word to google for.
Same question goes for entity properties.
Thank you.
Update:
Lets say I have a User class like so:
#NodeEntity(label="Person")
class User {
#Property(name="username")
private String name;
...
}
I've used the Mapping to obtain loose coupling so I can eg. rename the Person and won't affect the Neo4j.
And in the Neo4j there are for example Houses with Relationships to Users.
Now I want to load all Houses, referencing a User with the name "Sven", so the Statement would be MATCH (h:House)-[:HOLDS]->(p:Person {username:'Sven'}).
Given, that I might have a huge poject with all the entities in some submodule somewhere else, I might not know, that User is mapped to Person and the user.name is mapped to username, so in a Hibernate environment, I would query as MATCH (h:House)-[:HOLDS]->(u:User {name:'Sven'}). However in OGM this doesn't seem to work.
There might be a way to solve this architectually but in some projects you don't have this choise.
So the question in the End is: Is there some way to get this to work, or do I really need to know the mapping of every entity i use?
You can do this in several ways :
Make your User extend a Person class
if you need more dynamic labels, the class can contain an #Labelsannotated list of labels to apply. See the documentation for more details
About properties, I don't see how this would be useful. Interested to hear about the use case.
Related
I've got a domain called Planning that has a hasMany of another domain called Employee included in it. I'm trying to do a findAll of these plannings where the plannings contain a particular employee and I can't get it to work.
I'm trying to do it like so, my print statements do print the contains as true
plannings = plannings.findAll{planning->
if(employee) {
log.info("find plannings with employee ${employee} ${planning.employees.contains(employee)}")
planning.employees.contains(employee)
}
}
I'm not doing this as a Hibernate query as this broke the application in another weird way. This code is executed in a for each and for whatever reason that causes some weird behavior with Hibernate.
The closure must return a boolean value - see http://docs.groovy-lang.org/latest/html/groovy-jdk/java/util/Collection.html#findAll(groovy.lang.Closure)
This should work (not tested):
plannings = plannings.findAll{planning-> planning.employees?.contains(employee)}
BTW: I wouldn't assign the filtered list to the origin plannings list. Extract a a new expressive variable like planingsOfEmployee or something similar.
Without more relevant details around your problem (what's the weird behavior? log traces? hibernate mappings?, etc.) all we can do is to speculate; and if I have to do so, I would say that most likely:
The employee object you are using for comparison is a detached one.
The employee object does not override meaningfully equals and hashCode
You use using this detached employee to do comparisons against against persisted employees (using planning.employees.contains(employee)) found inside planning
Under these circumstances the comparisons will never be true even when they may represent the same objects. If this is your case, you must either:
Use a persisted employee object to do the comparisons.
Or, implement equals and hashCode semantically meaningful for Employee
Hope this helps.
Let's say we want to make an ontology model for the Light Switches in the home.Each Light Switch has two properties hasID, and hasLocation.
which way is the most correct way to doing it.
making a class LightSwitch
a data property hasID
an object property hasLocation
some individual Like LightSwitch-01, LightSwitch-02
OR
making a class LightSwitch
subclasses KitchenLightSwitch, LivingroomLightSwitch, and etc.
a data property hasID
an object property hasLocation
some individual Like LightSwitch-01, LightSwitch-02
In ontology design there is no right or wrong in general (of course there are situations where someone makes mistakes in the design process).
There is no such thing like "this is the one and only solution". There are always different solutions, based on your scenario, experience and what you would like to do with the ontology.
In your case you could solve your problem with both approaches (I would prefer the second one, since I'm a fan of classes). The only difference in your example that I see is that in the first one all lightswitch instances are of the type "LightSwitch" and in the second one the instances are of theire location type (e.g. KitchenLightSwitch).
However if you are using the object property "hasLocation" you do not really need subclasses for "LightSwitch".
Create a class "Lightswitch" with the instances "Switch1, Switch2,..." and create a class Room with instances (Kitchen, Livingroom, etc).
In the last step you associate a relationship: Switch1 hasLocation Kitchen.
Another possibility would be to create the class Room and subclasses LivingRoom, KitchenRoom, etc. Each of the subclasses would have an instance "kitchenroom, livingroom, etc."
But really, its up to you. I see nothing wrong with both of your solutions. However, if you would provide more information or your context would be more complex.. maybe then one could prefer either solution A or solution B, but for exactly this example that you are asking for, both solutions are right.
I am struggling with something I think should be basic but cannot figure out. I have two entities in core data with a one to one and one to many relationship. They are Company which can have multiple Opportunities.I want to load a table view listing the opportunities (sorted by name) with their associated companies. Can this be done by simply accessing the Opportunity entity? If so, how do I access company? The Opportunity class references it as a "Company" type and so I tried to go using dot notation through to company.companyName but it failed on that, and if I change it to simply company (of type Company) it does show .Company: and other reference data but not the simple name field I am looking for. This seems as if it should be simple but...........
This was simple and I was overlooking the ability to load the fetchedresultscontroller with the right type (in my case the Opportunity class) and then use dot notation from there. I was trying to do it with key value access which did not work. Cheers
I have two entries in a domain entity that I want to merge. Let's call the parent House and the children Room. I have a situation where I want to merge two House domains that are actually the same. I have the logic to do this top level merge.
However, I want to know if there is a way in Grails to easily say, 'go through the domain objects and wherever there is a fk pointer to House, update that fk to a new value'.
The code would be something like this
houseInst1.magicMerge(houseInst2)
This would run the House merge as well as check for every domain object that has a pointer (fk) to House and update where it points to houseInst2 originally to point to houseInst1.
Update: One key feature is that I'd like this to work if someone adds another domain object with a link to the master object. eg. if someone added Mortgages later, I don't want to update all my merge logic, it should go and find that Mortgages is a child of House, and update accordingly.
Grails domain objects expose the hibernate merge() method, but this does something completely different: it merges a (possibly detached) object back into the persistence context.
I'm not aware of any built in functionality to merge two objects like you describe. I think you need to manually update the foreign keys as in Gregg's answer. A more efficient way to do the update would be through HQL like so:
Room.executeUpdate('update Room set house = :newHouse where house = :oldHouse',
[newHouse: newHouse, oldHouse: oldHouse])
Edit: to automatically update all the associations, you can interrogate the Artefact:
def artefact = grailsApplication.getArtefact("Domain", "House")
artefact.associationMap.values().each { associationClass ->
associationClass.executeUpdate("update ${associationClass.simpleName} set house = :newHouse where house = :oldHouse",
[newHouse: newHouse, oldHouse: oldHouse])
}
How about something like this? You'll want to do this before you get rid of the old house.
Room.findAllByHouse(oldHouse).each { room ->
room.house = newHouse
room.save()
}
I haven't tried this and I'm assuming a pretty standard OneToMany relationship between House and Room.
i have a requirement to allow the user to define some custom field in one of the system entities. do you have any suggestion/pattern/plugin that will help me add this feature to my application.
thanks,
Meni
You can add a Map property to your domain class and store arbitrary data there. It's rather limited though. It will generate a table with varchar(255) keys and values, so you need to manage any type conversions yourself, e.g.
class Thing {
String name
Map extraProperties = [:]
}
int age = 123
def thing = new Thing(name: 'whatever')
thing.extraProperties.age = age.toString()
thing.save()
...
def thing = Thing.get(thingId)
int age = thing.extraProperties.age.toInteger()
See section "5.2.4 Sets, Lists and Maps" at http://grails.org/doc/latest/ for the brief online docs.
Sounds like you want your application to be an infinitely adjustable wrench that users can modify at will. Is that fair?
I don't think it's possible or desirable. Think about what happens when you add an attribute to an existing domain object in Grails. The attribute is added to the ORM mapping, which means the tables have to be modified. The UI has another text box added for data entry; the list page has another column added to its table.
There's a lot going on when you add an attribute. How will you manage multiple users modifying the app all at the same time? What happens when one user is modifying a table while another is accessing the old version?
You ask too much. I don't think it's a reasonable requirement. Grails' sweet spot is rapid development of web-based CRUD applications. I don't think that includes modification by users at runtime.