Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
11-30-2020 09:32 AM
Hello @gerrit.meier
I can't find anything in the SDN docs about indexing ... No more @Index and autoIndex(AutoIndexMode.UPDATE)?
Cheers, Chris
12-02-2020 12:41 AM
Also:
What about repository level events like onPostSave
and onPostDelete
(from OGM's EventListenerAdapter
)?
12-02-2020 09:31 AM
I had to import OGM and use their labels (@Index
) even though I had SDN6 imported. I also had to configure the SessionFactory
to enable the autoIndex("update")
12-02-2020 10:17 AM
Is that really what SDN 6 should be?
We need stuff from the old libs?
I also found out today that (bidirectional) @Relationship mappings don't really work and I wonder if this is by design ... because relationships get deleted!!!
For example:
@Node
class A {
....
@Relationship List<B> bs;
...
}
@Node
class B {
@Relationship A a;
}
If you now load an A entity, add a new B to the list of bs
and save A or B, then all the connections to existing Bs get deleted! Digging into this I found that the Bs in the List have a
set to null (do not get hydrated with A when A loads)
Haven't tried other (more complex) mappings yet but I guess it will be even worse and connections will get lost (because things only get loaded to depth 1???)
12-03-2020 02:10 AM
We intentionally did not re-implement this in SDN 6. The feature itself brought a lot of customer confusions (mainly because of the asynchronous nature of the index creation) but also created a lot of maintenance to handle every support database version right.
And in the end it is not a feature from an O[G/R/*]M but something that should be solved on the database side, say DBA or other tooling. For this we created https://github.com/michael-simons/neo4j-migrations or you could use https://github.com/liquibase/liquigraph.
No, please don't 😉
Yes, relationships will get deleted but this should of course not happen if A
(and its related entities) were loaded and hydrated. Could you provide an example with a little bit more information about the Node
classes (like id type, generated or not..) or even better a failing test scenario.
Also the assumption that we load with depth 1 is wrong because there is no limitation.
12-03-2020 03:33 AM
Hi @gerrit.meier Thank you for your reply!
The @Index
is - was - a REALLY awesome feature because the Java classes are effectively a schema for a schemaless DB and what better place to define which fields should get an index than in the schema?
Without this, it is definitely a step backwards and I have to go back abut 4 years and maintain a file of Cypher statements to drop/create indexes when deploying new app versions
Also very important and missing now:
@Id @GeneratedValue Long id
) or some other calculated values@DomainEvents
is great for some certain things but not for this (unless I am completely wrong and missing something ? but I can't see how I would get the info if the entity was created/updated/deleted).
Of course I could publish an applicationEvent EVERYWHERE I save/delete an entity but I think it would be much better (and easy to implement?) if Neo4jTemplate & Repositories published some generic Neo4j events that we can listen for (possibly enabling this feature with a @EnableNeo4jEvents
).
No?
Importing old libs: Didn't think so, don't want to 😉
Regarding the bidirectional relationship: I haven't used those for years because it always caused problems with OGM and now I thought with the new SDN6 I would give it a try again. So here is a compact version of what I want to do:
public abstract class Node {
@Id @GeneratedValue @Getter private Long id;
@Version @Getter private Long version;
@CreatedDate @Getter private LocalDateTime created;
@LastModifiedDate @Getter private LocalDateTime modified;
@Getter private String uuid; // <-- see nescessary onPreSave above!
}
@Node
@Getter
@Setter
public class Page extends Node {
private String title;
...
@Relationship(type = "PAGE", direction = Relationship.Direction.INCOMING) private List<File> files = new ArrayList<>();
}
@Node
@Getter
@Setter
public class File extends Node {
@Relationship(type = "PAGE") private Page page;
private String name;
...
}
// add a new file:
Page page = pageRepo.findById(id).get();
File file = new File();
file.setPage(page);
// option 1:
fileRepo.save(file); // deletes all existing connections between page and other files
// option 2:
page.getFiles().add(file);
pageRepo.save(page); // also deletes all existing connections between page and other files
// here: only the new file is connected to the page anymore
The existing files [loaded when the page is loaded] all have a getPage()
of null (!) and by saving the page [either directly or indirectly through saving the new file] deletes the existing relationships.
12-03-2020 03:52 AM
Regarding onPreSave / onPostSave / onPostDelete:
I am thinking something like this (not sure if this is really the best way to go but you get my point):
@EventListener
public void handleNeo4jEvent(Neo4jEvent event) {
if (event.getEntity() instanceof MyBaseNode) {
if (event.getType() == Neo4jEventType.PRE_SAVE) {
MyBaseNode node = (MyBaseNode) event.getEntity();
if (StringUtils.isBlank(node.getUuid())) node.setUuid(UUID.randomUUID().toString());
}
}
}
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleNeo4jAfterCommit(Neo4jEvent event) {
if (event.getEntity() instanceof Page) {
if (event.getType() == Neo4jEventType.SAVED) {
// update external index or file system
} else if (event.getType() == Neo4jEventType.DELETED) {
// delete entry from index, delete files from FS
}
}
}
12-08-2020 06:51 AM
Actually it would be best to be able to receive events for CREATED, UPDATED and DELETED (not just saved and deleted like my previous post might suggest)
Background: I regularly push info about object C(R)UD events to clients via web-sockets
All the sessions of the conference are now available online