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

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.

Hello @lingvisa :slight_smile:

Did you have a look at full-text search?

Regards,
Cobra

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 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?

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 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 :slight_smile:

Regards,
Cobra

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.

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