The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Graph-powered search combines two different jobs: Elasticsearch (or another search engine) retrieves textually relevant documents, while Neo4j supplies relationships for recommendations, expansion, filtering, personalization, and ranking. DZone Refcard #252, Graph-Powered Search: Neo4j & Elasticsearch, describes this pattern through a product-search example. Its architecture is still useful, but its Neo4j 3.3-era plugins, typed Elasticsearch mappings, and explicit Lucene-index procedures are historical rather than copy-and-paste instructions for a 2026 system.
What the DZone Refcard proposes
The Refcard, written by Alessandro Negro, Michael Hunger, and Christophe Willemsen, treats Neo4j as the connected domain model and Elasticsearch as a search-oriented read layer. Its main example combines products, sellers, suppliers, offers, categories, customer behavior, promotions, and feedback. A graph query can discover meaningful relationships; Elasticsearch can then retrieve and rank documents quickly.
As an Amazon Associate I earn from qualifying purchases.
The original resource is DZone Refcard #252, with the complete examples in the GraphAware-hosted PDF. Neo4j described it as a new resource in its December 9, 2017 weekly roundup.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
The durable idea is not “run a graph query instead of a search query.” It is a retrieval-and-enrichment pipeline:
#1 Best Overall
- Retrieve a candidate set with lexical, semantic, or vector search.
- Obtain graph-derived features, candidates, filters, or explanations.
- Normalize and combine those signals under explicit business and authorization rules.
- Return results with a freshness and relevance model the team can measure.
Why text search alone is not enough
Lexical search is excellent at matching words such as “red running shoes.” It does not inherently know that a customer bought a compatible shoe last month, that two products are commonly purchased together, that a part fits a particular machine, or that a document is connected to a user’s permitted organizational unit.
Those are relationship questions. They can involve category hierarchies, substitute brands, suppliers, friends, similar users, permissions, or several hops of inferred connection. Flattening every possible relationship into one document creates large, frequently changing indexes and still loses the ability to ask arbitrary relationship questions.
Which system does what?
| Concern | Neo4j | Elasticsearch |
|---|---|---|
| Connected domain model | Natural fit for entities and relationships | Usually represented by denormalized fields |
| Multi-hop traversal | Core capability | Typically precomputed or awkward at query time |
| Full-text retrieval | Supported through Lucene-backed full-text indexes | Core capability with analyzers and query DSL |
| Facets and aggregations | Possible, workload-dependent | Core search capability |
| Recommendations | Generate from relationship patterns | Usually stores materialized recommendation fields |
| Vector search | Supported with native vector indexes | Supported |
| Search projections | Source or projection generator | Read-optimized index |
| Authoritative graph transactions | Strong fit when the graph is the source of truth | Usually a derived search representation in this architecture |
Elasticsearch handles analysis, tokenization, stemming, stop words, synonyms, query parsing, aggregations, highlighting, and fast retrieval over search-shaped documents. The Refcard discusses JSON Query DSL clauses such as match, term, range, bool, and dis_max. In a modern design, treat the index as a derived read model: events can be delayed, duplicated, replayed, or applied out of order.
Neo4j maintains the connected model and can answer questions about paths, neighborhoods, category ancestry, similar users, co-purchases, and relationship-aware permissions. Neo4j also now offers native full-text, vector, and hybrid retrieval, so Elasticsearch is a choice rather than an automatic requirement. See the current documentation for semantic indexes and hybrid search.
One knowledge graph, multiple search views
The Refcard’s “single knowledge graph, multiple views” pattern projects the same connected domain into documents shaped for different experiences:
Rank #2
- General product and category search
- Faceted navigation and autocomplete
- Product-detail and seller pages
- Recommendations and personalized results
- Localized or language-specific content
Each materialized view needs an explicit graph extraction query, document identifier, field list, analyzer and mapping, update behavior, and delete behavior. Give every projection a versioned schema, ownership, source watermark, rebuild procedure, drift checks, and a policy for missing source data. A projection is an operational component, not a passive export.
Two ways to add graph intelligence to search
Post-search graph reranking
- Send the user’s text query to Elasticsearch.
- Retrieve a deliberately large candidate set.
- Ask Neo4j for graph features, graph filters, or relationship-derived scores for those candidates.
- Normalize the features, apply authorization and business constraints, and rerank.
- Return the final page and an explanation where appropriate.
This is easy to add to an existing search stack and keeps lexical retrieval in Elasticsearch. Its costs are extra round trips, graph work proportional to the candidate set, and the possibility that a relevant item outside the initial set can never be recovered.
Recommended Free Tools
Pre-search graph enrichment
- Query Neo4j for a user’s interests, related entities, permitted categories, or concepts.
- Translate those results into terms, boosts, filters, synonyms, or query expansions.
- Submit the enriched query to Elasticsearch for final retrieval and ranking.
This can reduce per-candidate graph work and latency, but large personalized expansions can become expensive, lower precision, or amplify popularity bias. Query construction and relevance debugging also become more complex.
Graph-generated candidates
For recommendations such as “customers similar to this customer also bought,” Neo4j can generate candidates first. Elasticsearch can then apply text filters, availability, language, price, or other constraints. This is a different operation from reranking a text result set and should be measured separately.
Ranking without mixing meaningless scores
The Refcard shows Elasticsearch function_score applying a multiplicative weight of 1.1—a 10% boost—to documents satisfying a collaborative-filtering condition. That illustrates the mechanism, not a generally correct weighting.
Rank #3
BM25-style text scores, graph path counts, purchase frequency, vector similarity, freshness, inventory, and commercial signals have different scales and meanings. Do not multiply arbitrary values from Neo4j and Elasticsearch. Neo4j’s hybrid-search guidance recommends ranking separate result sources independently rather than comparing raw scores.
A safer pipeline is:
- Retrieve enough candidates to protect recall.
- Compute features such as
lexical_score,graph_affinity,co_purchase_count,category_distance,user_brand_affinity,inventory_available,freshness, andsemantic_similarity. - Normalize, calibrate, or convert each feature to a rank-based value.
- Apply hard constraints for authorization, availability, geography, and policy.
- Combine features with a transparent formula or learned ranker.
- Evaluate recall, nDCG, conversion, diversity, latency, and exposure concentration offline and online.
Modernizing the historical examples
Do not copy the original plugin instructions
The PDF references graphaware-server-community-all-3.3.x.jar and graphaware-neo4j-to-elasticsearch-3.3.x.jar. It also uses Elasticsearch typed mappings and older explicit Lucene-index procedures. Those examples document the 2017 environment; compatibility and maintenance must be verified for the exact Neo4j and Elasticsearch releases you deploy.
For example, the historical typed structure below is not a current Elasticsearch recipe:
"mappings": {
"customer": {
"properties": {
"name": { "type": "keyword" },
"description": { "type": "text", "analyzer": "english" }
}
}
}
Use the typeless index-creation API supported by your target Elasticsearch version instead. Likewise, CALL db.index.explicit.searchNodes(...) is historical. Current Neo4j full-text indexes use the supported full-text syntax documented in the Cypher manual and Operations Manual.
Current Neo4j full-text example
CREATE FULLTEXT INDEX productSearch IF NOT EXISTS
FOR (p:Product)
ON EACH [p.name, p.description];
CALL db.index.fulltext.queryNodes(
'productSearch',
$query,
{limit: 50}
)
YIELD node, score
RETURN node, score
ORDER BY score DESC;
Select analyzers, indexed properties, consistency settings, and query options for the target release and workload. Full-text indexes are powered by Apache Lucene.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesRank #4
Current vector and hybrid example
CREATE FULLTEXT INDEX abstractFulltext IF NOT EXISTS
FOR (a:Abstract)
ON EACH [a.text];
CREATE VECTOR INDEX abstractEmbeddings IF NOT EXISTS
FOR (a:Abstract)
ON a.embedding
OPTIONS {
indexConfig: {
`vector.dimensions`: 1536,
`vector.similarity_function`: 'cosine'
}
};
The dimension must match the embedding model; 1536 is only the documentation example. For current releases, prefer the Cypher SEARCH clause where supported. The procedure form remains for compatibility with earlier versions and is deprecated as of Neo4j 2026.04 according to the vector-index documentation. A newly created vector index may be POPULATING; check readiness with:
SHOW VECTOR INDEXES;
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Synchronizing Neo4j and Elasticsearch safely
Application-owned dual writes
Writing both systems in one request is simple to start, but they cannot normally share one atomic transaction. Retries, idempotent document writes, reconciliation, and a partial-failure policy are mandatory.
Transactional outbox
Commit the graph change and an outbox event together, publish events to a queue or stream, project them into Elasticsearch, retry failures, and retain the ability to rebuild from Neo4j. This usually gives clearer durability semantics than direct dual writes.
CDC or event streaming
A supported change-data-capture or streaming mechanism can maintain projections at scale. Require stable identifiers, event versions, ordering or version checks, idempotency, delete handling, dead-letter processing, replay, and a full-reindex path.
Periodic rebuilds
For moderate freshness requirements, build a new Elasticsearch index from Neo4j, validate counts and sample documents, then switch an alias atomically. This is operationally simple but cannot provide continuously fresh results.
Best Value
Failure modes that need design, not hope
Stale projections
A newly changed graph entity may not be searchable immediately. Version fields, a recent-change read fallback to Neo4j, short-lived caching, and an explicit freshness indicator can make that behavior visible. Eventual consistency may be acceptable for recommendations, but not automatically for inventory, pricing, authorization, or compliance.
Deletes and tombstones
A missed delete leaves a stale document discoverable. Use explicit delete events, tombstones where appropriate, reconciliation, periodic rebuilds, and alias-based replacement.
Candidate truncation
Reranking only Elasticsearch’s top 10 means a graph-relevant result at rank 100 cannot enter the final list. Increase the candidate window until recall and latency measurements justify the cost.
Authorization leakage
A search hit is not automatically authorized. Apply permission checks before presentation and account for the security limitations documented for Neo4j’s Lucene-backed semantic indexes. Conservatively excluding results can produce partial result sets.
Graph explosion and feedback loops
Cap traversal depth and neighbor counts, use time windows and minimum interaction thresholds, and precompute or cache stable features. Monitor whether popularity boosts concentrate exposure, suppress new items, or create filter bubbles; add diversity and exploration constraints where needed.
Projection drift
Track graph entity count, search-document count, missing and orphan documents, latest event lag, projection errors, schema versions, and analyzer changes. These measures reveal silent divergence before users report it.
When a two-platform design is justified
| Situation | Likely fit | Reason |
|---|---|---|
| Industrial-scale lexical search, faceting, highlighting, and autocomplete plus deep relationship logic | Neo4j + Elasticsearch | Each platform has a first-class workload |
| Graph is authoritative; search volume is moderate; minimizing synchronization matters | Neo4j-only hybrid search | Native full-text, vector, and hybrid indexes may be sufficient |
| Relationships are shallow and safely denormalized | Search engine alone | A graph source of truth may add unnecessary complexity |
| Graph is mainly used for offline analytics | Search engine plus batch or streaming features | Online graph traversal is not central to retrieval |
| Strict synchronous consistency across graph and search is required | Reconsider the split | Dual systems introduce propagation boundaries |
Neo4j’s current pricing and feature matrix lists Community, self-managed Enterprise, and AuraDB managed options. AuraDB Free is listed at $0; the pricing page showed AuraDB Professional from $65/GB/month with a 1 GB minimum and Business Critical from $146/GB/month with a 2 GB minimum on August 18, 2026. Prices and features can change. Elastic Cloud pricing is usage- and configuration-based; consult Elastic Cloud and its pricing page rather than assuming a universal monthly figure.
Bottom-line decision
Use the Refcard as an architectural pattern, not a current deployment manual. Keep Neo4j when relationships are central to candidate generation, filtering, personalization, or explanation. Keep Elasticsearch when specialized lexical retrieval, aggregations, and search operations justify a separate engine. Choose Neo4j’s native full-text, vector, and hybrid capabilities when they meet the workload and removing synchronization is the bigger win. In every case, make projections rebuildable, ranking features calibrated, permissions explicit, and freshness measurable.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

