debug-ito / greskell Goto Github PK
View Code? Open in Web Editor NEWHaskell binding for Gremlin graph query language
Home Page: https://hackage.haskell.org/package/greskell
Haskell binding for Gremlin graph query language
Home Page: https://hackage.haskell.org/package/greskell
Thanks for this repo! I can't wait to dig in.
It took me a day of work to get Greskell working. I'm hoping that by sharing this recipe I can save others some time. The problem is mostly not in Greskell; it's that there are a gazillion ways to use Gremlin. Eventually I struck on the following, which works:
docker run --name gremlin -p 8182:8182 tinkerpop/gremlin-server:3.4.2
(if that's still the latest version). (I've added the -name and -p arguments; the first is optional, but the second is critical.)hspec
to the build-depends
list in greskell/greskell/greskell.cabal
.submit to the Gremlin Server
code from the README into a file called something like test-server.hs
.import Test.Hspec
. Second, so that you can see whether it's actually working, add print statements to the case statement. For convenience, here's the result of those substitutions:import Control.Exception.Safe (bracket, try, SomeException)
import Data.Foldable (toList)
import Data.Greskell.Greskell (Greskell) -- from greskell package
import Data.Greskell.Binder -- from greskell package
(Binder, newBind, runBinder)
import Network.Greskell.WebSocket -- from greskell-websocket package
(connect, close, submit, slurpResults)
import Test.Hspec
submitExample :: IO [Int]
submitExample =
bracket (connect "localhost" 8182) close $ \client -> do
let (g, binding) = runBinder $ plusTen 50
result_handle <- submit client g (Just binding)
fmap toList $ slurpResults result_handle
plusTen :: Int -> Binder (Greskell Int)
plusTen x = do
var_x <- newBind x
return $ var_x + 10
main :: IO ()
main = hspec $ specify "submit" $ do
egot <- try submitExample :: IO (Either SomeException [Int])
case egot of
Left _ ->
print "LEFT" >> return () -- probably there's no server running
Right got ->
print "RIGHT" >> (got `shouldBe` [60])
stack ghci
:l test-server
, then run main
.RIGHT
to the screen.main
should instead print LEFT
.If there's a more elegant solution, I'm all ears!
It would be convenient to make an automated way to save/load a record data type to/from Gremlin properties.
Maybe we can borrow ToForm
and FromForm
typeclasses of http-api-data. However, we would also need a way to generate a Key
data type for each record field...
As seen on the Stackage build server:
Failures:
test/Data/Greskell/GraphSONSpec.hs:94:7:
1) Data.Greskell.GraphSON.GrpahSON.parseTypedGraphSON.Int32 typed JSON with valid @type field and invalid @value
predicate failed on: "Error in $: parsing Int32 failed, expected Number, but encountered String"
To rerun use: --match "/Data.Greskell.GraphSON/GrpahSON/parseTypedGraphSON/Int32/typed JSON with valid @type field and invalid @value/"
test/Data/Greskell/GraphSONSpec.hs:114:7:
2) Data.Greskell.GraphSON.GrpahSON.parseTypedGraphSON.HashMap typed JSON with valid @type field and invalid @value field
predicate failed on: "Error in $: parsing HashMap failed, expected Object, but encountered Number"
To rerun use: --match "/Data.Greskell.GraphSON/GrpahSON/parseTypedGraphSON/HashMap/typed JSON with valid @type field and invalid @value field/"
Note that in aeson-1.4.3.0, the textual output of error messages changed slightly. As far as I can tell, this test failure is benign and the "fix" is merely to update test expectations.
See also: https://hackage.haskell.org/package/aeson-1.4.3.0/changelog
In an earlier issue, you wrote:
in your last example ("I see the property, but no value:"),
that was probably because you used () as property value type.
If the property value is (), greskell won't try parsing the
value at all and just return (). Use Int instead in this case.
However, I had not actually specified the type ()
. Rather, I had omitted the type signature. Experimenting after your comment, I found that if I use a type variable, it's as if I specified ()
:
findPeopleProperties :: [Key AVertex d]
-> GTraversal Transform () (AVertexProperty d)
Is this behavior intentional? It seems as if ()
serves as the default type when none is specified -- but even when the type is unspecified (as in the variable d
above), the AVertexProperty
object indicates the payload's type, as in the flagged line below:
AVertexProperty
{ avpId = GValue
{ unGValue = GraphSON
{ gsonType = Just "g:Int64" # flag
, gsonValue = GNumber -2.042816214e9 } }
, avpLabel = "suchness"
, avpValue = ()
, avpProperties = PropertyMapSingle
( PropertyMapGeneric ( fromList [] ) ) }
Therefore a more closely-fitting default type might be possible.
I found an email thread on bidirectional search, in which Marko Rodriguez offers two implementations:
g.v(1).outE.inV.loop(2){it.object != g.v(2)}.retain([g.v(2)]).path
g.v(1).outE.inV.loop(2){isSimple(it.path) & it.object != g.v(2) & it.loops < 4}.retain([g.v(2)]).path
(He provides the second because the first "traversal is scary cause you could have infinite loops and reverberating paths.")
They contain some steps I'm unable to find in Greskell. retain
appears to be a synonym for filter
, and !=
I believe is the same as .neq
. But I see no equivalent for loop
, loops
, it
, object
or path
.
loop
in particular appears to be important, as it permits recursion.
I figured out how to add a vertex:
runSideEffect :: GTraversal SideEffect () AVertex
-> IO (Either SomeException [AVertex])
runSideEffect script = try go where
go :: IO [AVertex]
go =
bracket (connect "localhost" 8182) close $ \client -> do
result_handle <- submit client script Nothing
fmap toList $ slurpResults result_handle
addPerson :: Int -> GTraversal SideEffect () AVertex
addPerson n = source "g" &
sAddV "person"
-- &. gProperty "suchness" (valueInt n)
Notice that the last line is commented out. If I run that, I get something like this:
Right [AVertex {avId = GValue {unGValue = GraphSON {gsonType = Just "g:Int64", gsonValue = GNumber 3.0}}, avLabel = "person", avProperties = PropertyMapList (PropertyMapGeneric (fromList []))}]
I hoped the commented-out line would add an Integer-valued property called "suchness" to the vertex. But if I uncomment that line, I get the same result -- the property map remains empty.
I figured out how to add a vertex:
runSideEffect :: GTraversal SideEffect () AVertex
-> IO (Either SomeException [AVertex])
runSideEffect script = try go where
go :: IO [AVertex]
go =
bracket (connect "localhost" 8182) close $ \client -> do
result_handle <- submit client script Nothing
fmap toList $ slurpResults result_handle
addPerson :: Int -> GTraversal SideEffect () AVertex
addPerson n = source "g" &
sAddV "person"
-- &. gProperty "suchness" (valueInt n)
Notice that the last line is commented out. If I run that, I get something like this:
Right [AVertex {avId = GValue {unGValue = GraphSON {gsonType = Just "g:Int64", gsonValue = GNumber 3.0}}, avLabel = "person", avProperties = PropertyMapList (PropertyMapGeneric (fromList []))}]
I hoped the commented-out line would add an Integer-valued property called "suchness" to the vertex. But if I uncomment that line, I get the same result -- the property map remains empty.
Apologies if I'm missing something, but I can't find the match() step for Graph Traversal.
This would provide a declarative way of traversing the graph, which is extremely useful.
Would it be possible to add this to the API?
See also: #5
When a Gremlin Server returns Vertex objects, it's possible that properties
attribute is omitted (it doesn't have the key in the first place), although this is a violation of GraphSON IO format. I'm not sure what is reponsible for this problem, but I suspect the Graph implementation. And also I suspect such implementations omit properties for Edges.
For interoperability, greskell should be able to parse the graph elements without properties
attribute. That case should be tested.
This repo has a great DSL, but every time I write some function that returns a Walk (especially abstract over WalkType) it becomes a huge pain to match the walk type, because it's easy to get lost in all the '
, liftWalk
, >>>
, etc, so I'm wondering if it's me doing something wrong.
Thank you.
I want to manipulate a graph hosted by Gremlin Server. Greskell will let me do most things, and I've gotten to hello world with it, so to speak -- when I start Gremlin Server in a Docker container, I can interact with it from GHCI. (The README lists the steps I take to do that.)
Greskell, however, seems to provide no indexing facilities. (Nor does Gremlin itself provide abstractions for indexing, but Gremlin does provides plugins for specific implementations, e.g. Neo4j.)
If I've got a graph hosted by Gremlin Server, and I want to use Greskell (at least most of the time) to manipulate it, is there a way to index certain properties?
Hackage offers hasbolt for manipulating neo4j graphs directly. If I were to use that, I would have to somehow tell Gremlin Server to use Neo4j (I don't know what it uses by default), and then point hasbolt at Gremlin Server, which for all I know doesn't even make sense.
(This might be TMI, but I tried to make a custom Docker image for Gremlin Server that includes a few neo4j config files borrowed from another project. The result ought to be launchable via /opt/gremlin-server/bin/gremlin-server.sh /mnt/config/gremlin-server.yaml
, but when I do that I get parse errors.)
Current greskell supports use of .from
and .to
modulators for .addE
step that take Traversal argument, but there are more uses about them.
.from
and .to
modulators can be applied to .path
, .simplePath
and .cyclicPath
steps..from
and .to
modulators can also take step labels.If you need this extension, just add a comment to this issue.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.