cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

How to do 'keyword' based search on neo4j across different node types?

lingvisa
Graph Fellow

The typical search in neo4j is to write query with restrictions and the node type is an important restriction type. For example:

match (n:Product) where n.name='iPhone' return n

However, if the user doesn't know what node type should be given, he may just write query:
match (n) where n.name='iPhone' return n

And this 'iPhone' may be names of one or another node types, such as Product, or Brand. To make the query more efficient, I may have a function working behind the scene and convert user's keyword search into this query:

match (n)
where (n:Product or n:Brand) and n._name = 'iPhone' 
return n

This takes 150 ms shown in the browser, while this one only takes 1 ms:

match (n:Product) where n._name = 'iPhone' 
return n

Is there a more efficient way to support users' such queries? Given a keyword without other restrictions, the query return any nodes that may hit this query.

9 REPLIES 9

Hello @lingvisa

Did you have a look at full-text search?

Regards,
Cobra

I know of full-text search. Can I build a single fulltext index from different nodes? I used to create fulltext index on a single property of a single node. In the use case above, how can I create a single index to meet the requirements?

clem
Graph Steward

I don't know if you know this, but Nodes can have multiple Labels.

You could make a Label that is a Superset of all types of nodes you want to query, e.g. BrandProduct.

When you create a node, then you would have:

CREATE (p:Brand:BrandProduct {name:'iPhone'}) or CREATE (p:Product:BrandProduct {name:'iPhone'})

Then your query would be:

match (n:BrandProduct) where n._name = 'iPhone' 
return n

You can also add new Labels to existing Nodes.

I could think about this, by adding additional label to exsiting nodes.

Try this:

MATCH (n) 
WHERE exists (n.name) and labels(n) in [['Product], ['Brand']
and n.name = 'iphone'
RETURN n

@ameyasoft It works, but it's a big slower than this version:

match (n) where n.name = 'iPhone
 return n

All takes over 100 ms. I already created index on the 'name' property for all node types. Why isn't faster?

Only this takes 1 ms:

match (n:Product) where n.name='iPhone'
return n

You can Profile this (using Neo4J's PROFILE or EXPLAIN), but I suspect that in the first version, (without specifying the Label) means there are a lot more nodes to go through.

I believe by limiting the Nodes to one type ('Product'), there's less to go through.

You only need one full-text index, you can create it like this:

CALL db.index.fulltext.createNodeIndex("nameProductBrand", ["Product", "Brand"], ["name"])

To use it:

CALL db.index.fulltext.queryNodes("nameProductBrand", "iPhone") YIELD node, score
RETURN node, score

It should be the fastest method

Regards,
Cobra

@Cobra I will try this, probably it's what I need.