Here is an example of one way you might do it, but as I mentioned in my comment above, the presence of one or more edges really indicates the same thing that a shared
property might indicate.
Assuming this small graph
g.addV('Product').property('shared',false).property('pid','p1').as('p1').
addV('User').property('name','Name').property('uid','u1').as('u1').
addE('SharedBy').from('p1').to('u1')
You can do
gremlin> g.V().has('pid','p1').coalesce(filter(out('SharedBy')).property('shared',true),property('shared',false))
==>v[61293]
gremlin> g.V().has('pid','p1').valueMap()
==>[shared:[true],pid:[p1]]
We can drop the edge and re run the query to prove it works
gremlin> g.E(61299).drop()
gremlin> g.V().has('pid','p1').coalesce(filter(out('SharedBy')).property('shared',true),property('shared',false))
==>v[61293]
gremlin> g.V().has('pid','p1').valueMap()
==>[shared:[false],pid:[p1]]
Note that it is not required that the property already exist in some form. I included it that way in my example but that is totally optional. It is usually faster to check for the existence rather than the non-existence of a property however so that is something to consider. A tradeoff between efficiency and storing potentially a lot of extra properties in the graph.