I'm using the Neo4j
graph DB with Neo4jClient
and I'm trying to execute a search query on nodes, where the result should return a list of nodes that contain a given query string.
I have this working, but it seems inefficient as I'm bringing all the Groups
back and then filtering. Is there a better way?
internal object SearchGroups(string query)
{
var groups = WebApiConfig.GraphClient.Cypher
.Match("(g:Groups)")
.Return(g => g.As<Groups>())
.Results;
List<Groups> groupList = new List<Groups>();
foreach (var item in groups)
{
if (item.GroupName.Contains(query))
{
groupList.Add(item);
}
}
return groupList;
}
I've seen examples that filter using .Where((Groups g)=> g.GroupName == query)
but this only returns if it matches, not if it Contains
.
Well, you're mostly there with the tag of regex
- you have 2 options depending on what you want to do, and what your query
is. First though - Please read the documentation for Cypher
and try your queries out in the Admin window (localhost:7474) first, you'll find it hugely beneficial. In particular for this the Where
documentation would have helped you a lot.
Option 1: Regex
var groups = WebApiConfig.GraphClient.Cypher
.Match("(g:Groups)")
.Where("g.GroupName =~ {nameParam}")
.WithParam("nameParam", string.Format(".*{0}.*", query))
.Return(g => g.As<Groups>())
.Results;
Cypher for this looks like:
MATCH (g:Groups) WHERE g.GroupName =~ '.*<your query text>.*' RETURN g
This is using a regex
- as a parameter which will work in the same way as Contains
. Using regex
like this is not performant, and it might be better if you can do something like....
Option 2: Starts With
This is only applicable if you're using Neo4j 2.3+
and your query
is a Starts With
type query, but would be significantly faster.
var groups = WebApiConfig.GraphClient.Cypher
.Match("(g:Groups)")
.Where((Groups g) => g.GroupName.StartsWith(query))
.Return(g => g.As<Groups>())
.Results;
Cypher for this looks like:
MATCH (g:Groups) WHERE g.GroupName STARTS WITH <your query text> RETURN g
PS
You really should return IEnumerable<Groups>
/ICollection<Groups>
/IList<Groups>
from your method instead of object
, and you could also replace your foreach
with:
var groupsList = groups.Where(g => g.GroupName.Contains(query)).ToList();
Or just return it:
return groups.Where(/*see above*/);