I database grafici hanno rapidamente guadagnato popolarità nell’architettura software program moderna, poiché i sistemi si basano sempre più su relazioni, raccomandazioni e dati connessi. Dalle piattaforme di social media e sistemi di rilevamento delle frodi ai motori di raccomandazione e ai grafici delle conoscenze, i database dei grafici offrono un modo potente per modellare e attraversare relazioni complesse che sono difficili da esprimere in modo efficiente nei database relazionali.
Questa seconda parte della serie restringe l’attenzione per Neo4j, il più importante motore di database grafico del mercato. Esploreremo la sua architettura, il linguaggio delle question (Cypher) e vedremo come gli sviluppatori Java possono sfruttare Eclipse JNOSQL 1.1.8 per integrarlo perfettamente nelle applicazioni Java.
Comprensione del neo4j
Neo4j è un database dei grafici nativi in modo esplicito per archiviare ed elaborare i grafici in modo efficiente ed efficace. Rappresenta i dati come nodi (vertici) e relazioni (bordi), che possono contenere proprietà. A differenza dei database relazionali, in cui le relazioni sono dedotte attraverso le chiavi straniere, NEO4J tratta le relazioni come cittadini di prima classe, con conseguenti attraversamenti grafici più veloci ed espressivi.
Alcune delle caratteristiche chiave che rendono popolare il neo4j includono:
- Un potente linguaggio di question: Cypher
- Modello transazionale conforme all’acido
- Traversali grafici advert alte prestazioni
- Browser di dati visivi e strumenti maturi
- Forte supporto comunitario e commerciale
Incontra Cypher: il linguaggio della question grafico
Cypher è il linguaggio di question dichiarativo di Neo4J progettato per esprimere intuitivamente i motivi grafici. La sua sintassi è familiare agli utenti SQL, ma è destinata a attraversare nodi e relazioni, non advert unirsi alle tabelle.
Ecco un rapido confronto:
Caratteristica | SQL | Cypher |
---|---|---|
Recupero di entità | Seleziona * dal libro | Match (B: E book) Return B |
Filtraggio | Dove title = “java” | Dove b.title = “java” |
Be part of/Relationship | Unisciti a Book_Category su … | Match (b: libro)-(: is)-> (c: categoria) return b |
Raggruppamento e conteggio | Gruppo per categoria_id | Con C, conta (b) come totale |
Flessibilità dello schema | Schema fisso | Grafico della proprietà, più dinamico |
Iniziare con neo4j ed eclipse jnosql
Eclipse Jnosql Semplifica l’integrazione del database aderendo alle specifiche di Jakarta EE, in particolare ai dati di Jakarta NoSQL e Jakarta. In questo campione, useremo Java SE e mostreremo come interagire con NEO4J usando un modello di dominio di libri e le loro categorie.
Innanzitutto, assicurarsi che Neo4j sia in esecuzione. Usa Docker per girarlo rapidamente:
docker run --publish=7474:7474 --publish=7687:7687 --env NEO4J_AUTH=neo4j/admin123 neo4j:5.26.3
Ora, configurare la connessione utilizzando Microprofile Config (che supporta le sostituzioni delle variabili dell’ambiente):
jnosql.neo4j.uri=bolt://localhost:7687
jnosql.neo4j.username=neo4j
jnosql.neo4j.password=admin123
jnosql.graph.database=neo4j
È possibile sovrascrivere qualsiasi configurazione grazie al fattore dell’applicazione di dodici. Advert esempio, è possibile aggiornare la password di produzione senza modificare una singola riga di codice. Quello che devi fare è impostare l’ambiente di sistema:
export JNOSQL_NEO4J_PASSWORD=PRODUCTION_PASSWORD
Entità di modellazione
Con NEO4J configurato ed in esecuzione, il passo successivo è definire il nostro modello di dominio utilizzando Jakarta Nosql Annotazioni. In questo esempio, ci concentriamo su due entità – E book
E Class
– che formerà i nodi fondamentali nel nostro grafico. Queste classi dimostreranno come inserire i dati e definire le relazioni usando NEO4J in modo pulito e idiomatico con Java.
@Entity
public class E book {
@Id
non-public String id;
@Column
non-public String title;
}
@Entity
public class Class {
@Id
non-public String id;
@Column
non-public String title;
}
Eclipse jnosql offre un Neo4JTemplate
una specializzazione di Template
per l’accesso NEO4J nativo. Questa API consente interazioni dirette con NEO4J usando question cypher, la creazione dei bordi e la persistenza dell’entità a livello di programmazione ed espressivamente.
Ecco come puoi incapsulare la logica di persistenza in un livello di servizio di base:
@ApplicationScoped
public class BookService {
non-public static closing Logger LOGGER = Logger.getLogger(BookService.class.getName());
@Inject
non-public Neo4JTemplate template;
public E book save(E book e-book) {
Non-obligatory discovered = template.choose(E book.class).the place("title").eq(e-book.getName()).singleResult();
return discovered.orElseGet(() -> template.insert(e-book));
}
public Class save(Class class) {
Non-obligatory discovered = template.choose(Class.class).the place("title").eq(class.getName()).singleResult();
return discovered.orElseGet(() -> template.insert(class));
}
}
Per dimostrare un ciclo di esecuzione completo, utilizziamo il BookApp
Classe, che inizializza un contenitore CDI, memorizza libri e categorie, crea bordi tra loro e esegue question cypher:
public closing class BookApp {
non-public BookApp() {}
public static void most important(String() args) {
attempt (SeContainer container = SeContainerInitializer.newInstance().initialize()) {
var template = container.choose(Neo4JTemplate.class).get();
var service = container.choose(BookService.class).get();
var software program = service.save(Class.of("Software program"));
var java = service.save(Class.of("Java"));
var structure = service.save(Class.of("Structure"));
var efficiency = service.save(Class.of("Efficiency"));
var effectiveJava = service.save(E book.of("Efficient Java"));
var cleanArchitecture = service.save(E book.of("Clear Structure"));
var systemDesign = service.save(E book.of("System Design Interview"));
var javaPerformance = service.save(E book.of("Java Efficiency"));
template.edge(Edge.supply(effectiveJava).label("is").goal(java).property("relevance", 10).construct());
template.edge(Edge.supply(effectiveJava).label("is").goal(software program).property("relevance", 9).construct());
template.edge(Edge.supply(cleanArchitecture).label("is").goal(software program).property("relevance", 8).construct());
template.edge(Edge.supply(cleanArchitecture).label("is").goal(structure).property("relevance", 10).construct());
template.edge(Edge.supply(systemDesign).label("is").goal(structure).property("relevance", 9).construct());
template.edge(Edge.supply(systemDesign).label("is").goal(software program).property("relevance", 7).construct());
template.edge(Edge.supply(javaPerformance).label("is").goal(efficiency).property("relevance", 8).construct());
template.edge(Edge.supply(javaPerformance).label("is").goal(java).property("relevance", 9).construct());
System.out.println("Books in 'Structure' class:");
var architectureBooks = template.cypher("MATCH (b:E book)-(:is)->(c:Class {title: 'Structure'}) RETURN b AS e-book", Collections.emptyMap()).toList();
architectureBooks.forEach(doc -> System.out.println(" - " + doc));
System.out.println("Classes with multiple e-book:");
var commonCategories = template.cypher("MATCH (b:E book)-(:is)->(c:Class) WITH c, depend(b) AS whole WHERE whole > 1 RETURN c", Collections.emptyMap()).toList();
commonCategories.forEach(doc -> System.out.println(" - " + doc));
var highRelevanceBooks = template.cypher("MATCH (b:E book)-(r:is)->(:Class) WHERE r.relevance >= 9 RETURN DISTINCT b", Collections.emptyMap()).toList();
System.out.println(" Books with excessive relevance:");
highRelevanceBooks.forEach(doc -> System.out.println(" - " + doc));
System.out.println(" Books with title: 'Efficient Java':");
var effectiveJavaBooks = template.cypher("MATCH (b:E book {title: $title}) RETURN b", Collections.singletonMap("title", "Efficient Java")).toList();
effectiveJavaBooks.forEach(doc -> System.out.println(" - " + doc));
}
}
}
Puoi anche sviluppare relazioni ed eseguire question cypher. L’esempio seguente mostra come definire un bordo tra due entità usando esplicitamente Edge
API fornita da Eclipse Jnosql. Questo bordo rappresenta una relazione con l’etichetta is
e embrace una proprietà, relevance
per esprimere la sua importanza.
Edge edge = Edge.supply(e-book).label("is").goal(class).property("relevance", 9).construct();
template.edge(edge);
Dopo aver creato i bordi, è possibile utilizzare Cypher per interrogare il grafico. Advert esempio, la seguente question recupera libri che hanno una relazione advert alta rilevanza (> = 9) a qualsiasi categoria:
var books = template.cypher(
"MATCH (b:E book)-(r:is)->(:Class) WHERE r.relevance >= 9 RETURN DISTINCT b",
Collections.emptyMap()
).toList();
Questi esempi dimostrano come Neo4JTemplate possa persistere e mettere in relazione le entità del dominio e navigare e analizzare le strutture grafiche con Cypher.
Fare riferimento a BookApp
Nel campione per la configurazione dei dati, l’inserimento, la creazione di relazioni e le question Cypher. Dopo aver inserito tali informazioni nel database, è possibile controllare la dashboard NE4J:
Puoi anche interagire con NEO4J utilizzando le interfacce del repository. Eclipse JNOSQL Supporta Neo4JRepository
Un’estensione dei dati Jakarta con supporto Cypher:
@Repository
public interface BookRepository extends Neo4JRepository {
Non-obligatory findByName(String title);
@Cypher("MATCH (b:E book)-(:is)->(c:Class {title: 'Structure'}) RETURN DISTINCT b")
Listing findArchitectureBooks();
@Cypher("MATCH (b:E book)-(r:is)->(:Class) WHERE r.relevance >= 9 RETURN DISTINCT b")
Listing highRelevanceBooks();
}
@Repository
public interface CategoryRepository extends Neo4JRepository {
Non-obligatory findByName(String title);
@Cypher("MATCH (b:E book)-(:is)->(c:Class) WITH c, depend(b) AS whole WHERE whole > 1 RETURN c")
Listing commonCategories();
}
IL BookApp2
La classe dimostra come utilizzare questi repository in pratica sostituendo il basso livello Neo4JTemplate
Utilizzo con l’astrazione del repository di Jakarta Knowledge. Questo approccio semplifica significativamente il codice consentendo l’accesso al potere espressivo di Cypher attraverso le annotazioni.
Questo esempio non solo mostra come persistere entità usando metodi di repository commonplace come findByName
ma anche come eseguire question grafiche complesse attraverso il @Cypher
annotazione. Inoltre, la creazione di Edge è ancora gestita tramite GraphTemplate
mantenendo la modellazione di relazione pienamente esplicita e sotto controllo.
Questo doppio modello-repository per l’accesso al dominio e modelli per le relazioni specifiche del grafico-offre un grande equilibrio tra convenienza e flessibilità, rendendolo ideale per modelli di dominio complessi con relazioni ricche.
import jakarta.enterprise.inject.se.SeContainer;
import jakarta.enterprise.inject.se.SeContainerInitializer;
import org.eclipse.jnosql.mapping.graph.Edge;
import org.eclipse.jnosql.mapping.graph.GraphTemplate;
public closing class BookApp2 {
non-public BookApp2() {
}
public static void most important(String() args) {
attempt (SeContainer container = SeContainerInitializer.newInstance().initialize()) {
var template = container.choose(GraphTemplate.class).get();
var bookRepository = container.choose(BookRepository.class).get();
var repository = container.choose(CategoryRepository.class).get();
var software program = repository.findByName("Software program").orElseGet(() -> repository.save(Class.of("Software program")));
var java = repository.findByName("Java").orElseGet(() -> repository.save(Class.of("Java")));
var structure = repository.findByName("Structure").orElseGet(() -> repository.save(Class.of("Structure")));
var efficiency = repository.findByName("Efficiency").orElseGet(() -> repository.save(Class.of("Efficiency")));
var effectiveJava = bookRepository.findByName("Efficient Java").orElseGet(() -> bookRepository.save(E book.of("Efficient Java")));
var cleanArchitecture = bookRepository.findByName("Clear Structure").orElseGet(() -> bookRepository.save(E book.of("Clear Structure")));
var systemDesign = bookRepository.findByName("System Design Interview").orElseGet(() -> bookRepository.save(E book.of("System Design Interview")));
var javaPerformance = bookRepository.findByName("Java Efficiency").orElseGet(() -> bookRepository.save(E book.of("Java Efficiency")));
template.edge(Edge.supply(effectiveJava).label("is").goal(java).property("relevance", 10).construct());
template.edge(Edge.supply(effectiveJava).label("is").goal(software program).property("relevance", 9).construct());
template.edge(Edge.supply(cleanArchitecture).label("is").goal(software program).property("relevance", 8).construct());
template.edge(Edge.supply(cleanArchitecture).label("is").goal(structure).property("relevance", 10).construct());
template.edge(Edge.supply(systemDesign).label("is").goal(structure).property("relevance", 9).construct());
template.edge(Edge.supply(systemDesign).label("is").goal(software program).property("relevance", 7).construct());
template.edge(Edge.supply(javaPerformance).label("is").goal(efficiency).property("relevance", 8).construct());
template.edge(Edge.supply(javaPerformance).label("is").goal(java).property("relevance", 9).construct());
System.out.println("Books in 'Structure' class:");
var architectureBooks = bookRepository.findArchitectureBooks();
architectureBooks.forEach(doc -> System.out.println(" - " + doc));
System.out.println("Classes with multiple e-book:");
var commonCategories = repository.commonCategories();
commonCategories.forEach(doc -> System.out.println(" - " + doc));
var highRelevanceBooks = bookRepository.highRelevanceBooks();
System.out.println("Books with excessive relevance:");
highRelevanceBooks.forEach(doc -> System.out.println(" - " + doc));
var bookByName = bookRepository.queryByName("Efficient Java");
System.out.println("E book by title: " + bookByName);
}
}
}
Conclusione
NEO4J offre potenti funzionalità di grafico a cui gli sviluppatori Java possono ora accedere in modo pulito e commonplace utilizzando i dati Eclipse JNOSQL e Jakarta. Sia che tu scelga di interagire tramite Neo4JTemplate
o sfruttare i repository di dati Jakarta. L’integrazione è liscia, di tipo-sicuro ed espressivo. Questo approccio ti consente di modellare relazioni complesse in modo nativo senza sacrificare i idiomi di Java o la produttività degli sviluppatori.