Gremlin filter one query's output based on another query - gremlin

I have two gremlin queries. I want to filter out the output of one query based on the results of another query.
For example,
query 1: g.V().hasLabel('Person').values('name') gives the following output - John, Sam, Rocky
query 2: g.V().hasLabel('Friend').values('name') gives the following output - John
So, the final expected output I want is John
I have tried the following:
g.V().hasLabel('Person').where('names', g.V().hasLabel('Friend').values('name'))
But it doesn't seem to be working. Can anyone please help me here?

I'm curious why you are not using edges to determine a friend type relationship, but one way to re-write this is to just to reverse the parts.
g.V().hasLabel('Friend').values('name')).fold().as('friends').
V().hasLabel('Person').
where(within('friends')).by('name').by()

Related

how to execute a query after getting response of another query?

I need the result of the first query to pass it as an input parameter to my second query. and also want to know to write multi queries.
In my use case, the second query can be traversed only using the result of the first query and that too using loop(which is similar to for loop)
const query1 =g.V().hasLabel('Province').has('code',market').inE('partOf').outV().has('type',state).values('code').as('state')
After executing query1,the result is
res=[{id1},{id2},........]
query2 = select('state').repeat(has('code',res[0]).inE('partOf').outV().has('type',city).value('name')).times(${res.length-1}).as('city')
I made the assumptions that your first query tries to finds "states by market" where the market is a variable you intend to pass to your query. If that is correct then your first query simplifies to:
g.V().hasLabel('Province').has('code',market).
in('partOf').
has('type','state').values('code')
so, prefer in() to inE().outV() when no filtering on edge properties is needed.
Your second query doesn't look like valid Gremlin, but maybe you were just trying to provide an example of what you wanted to do. You wrote:
select('state').
repeat(has('code',res[0]).
inE('partOf').outV().
has('type',city).value('name')).
times(${res.length-1}).as('city')
and I assume that means you want to use the states found in the first query to find their cities. If that's what you're after you can simplify this to a single query of:
g.V().hasLabel('Province').has('code',market).
in('partOf').has('type','state').
in('partOf').has('type','city').
values('name')
If you need data about the state and the city as part of the result then consider project():
g.V().hasLabel('Province').has('code',market).
in('partOf').has('type','state').
project('state','cities').
by('code').
by(__.in('partOf').has('type','city').
values('name').
fold())

Adding Multiple Unique Vertices

I want to write a single gremlin query that will create multiple vertices, but only does so if they are all unique. I know I can use the get or addV method by using coalesce step mentioned in the comments.
g.V().has('com.demo.test', '__type', 'Namespace').fold().coalesce(unfold(), addV('com.demo.test').property('__type', 'Namespace'))
This will hadd a single vertex only if it does not exist already. What if i want to do this same procedure for multiple edges and vertices all in a single query? My goal is that if one of the vertices/edges is not unique, none of them are created. However I understand that may not be possible so all answers are welcome.
Thanks
I found a possible solution. This works but there might be a better way to do it.
g.V().coalesce(
V().has(label,'Namespace61'),
addV('Namespace61')).
coalesce(
V().has(label,'Namespace76'),
addV('Namespace76')).
coalesce(
V().has(label,'Namespace74'),
addV('Namespace74')
).dedup()

Simple outer-join like gremlin query not returning any results

I wrote the simple query below to traversal between Person to Country but it’s not returning any results.
g.V().hasLabel("Person").as("p").out("from").hasLabel("Country").as("c").select("p", "c")
In the actual data, only Person vertices exists and no Country vertices or from edges exist. I expected to at least return p - basically I want to do a left outer join. However, if I have Country and from data as well, the query returns results.
I tried another query using match as well but still no results unless there are actual data:
g.V().hasLabel("Person").has("name","bob").match(__.as("p").out("from").hasLabel("Country").as("c")).select("p", "c")
I'm running these queries against Datastax Enterpise Graph.
Any idea why it’s returning no results?
The result you are getting is expected. If there are no "from" edges then the traverser essentially dies and does not proceed any further. Perhaps you could consider using project():
g.V().hasLabel("Person").
project('name','country').
by('name')
by(out('from').hasLabel('Country').values('name').fold())
With the "modern" toy graph in TinkerPop, the output looks like this:
gremlin> g.V().hasLabel('person').project('name','knows').by().by(out('knows').values('name').fold())
==>[name:v[1],knows:[vadas,josh]]
==>[name:v[2],knows:[]]
==>[name:v[4],knows:[]]
==>[name:v[6],knows:[]]
In the future, when you submit questions about Gremlin, please include a Gremlin script that can be pasted into a Gremlin Console which makes it easier to try to more directly answer your specific question.

Use "where in" for LiteDB

I enjoy working with LiteDB in Xamarin.Forms. What is the best practice for getting list of objects from a table using list of ids or indexes in condition?
Currently, it looks for me like this:
_db.GetCollection<T>().FindAll().Where(q => listValues.Contains(Convert.ToInt32(q.GetProperty(idColumnName))));
listValues - list of searched ids.
idColumnName - column with indexes.
But FindAll retrives all records from LiteDB. Is there any more efficint options without full scanning?
Use the query in the Find method instead which will only retrieve entries based on your query rather than the full data set. This, according to the LiteDB's guidance, is more efficient than Linq queries on the full data returned: https://github.com/mbdavid/LiteDB/wiki/Queries
So your query would look like as follows
_d.GetCollection<T>().Find(q => listValues.Contains(Convert.ToInt32(q.GetProperty(idColumnName))))
I think you can just use collection.Query().Where("Column", 1,2,3) for this

NEO4J Cypher query START index query with multiple nodes

Is it possible to write an cypher query that can START with an exact index query for multiple nodes?
For example:
START n=node:indexName (key="value1", key="value2" ...)
I was unable to achieve something like the above, I am about to explore whether this can be done with a lucene query.
Many Thanks.
I just asked a very similar question:
querying with an "IN" clause using the index in neo4j with Cypher
And Peter answered with the following
start n = node:indexName('key:123 OR key:456')
You can:
START thing1 = node:topic('name:(keyword1)'), thing2 = node:topic('name:(keyword2)')
it will look for two topics, containing each a different value;
start n=node:topic('name:(keyword1 AND keyword2)') return n
it will look for multiple keywords in the same node

Resources