grails查询使用rest客户端构建器在图形数据库上运行cypher查询

时间:2013-08-02 20:29:46

标签: grails groovy neo4j cypher

尝试使用此处的rest-client-builder插件

http://grails.org/plugin/rest-client-builder

在我的neo4j图表上运行cypher查询

所以我构建了一个完全符合我想要的groovy脚本

@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.5.0-RC2' )
@Grab(group='net.sf.json-lib', module='json-lib', version='2.4', classifier='jdk15' )

import groovyx.net.http.*
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*

def query(statement, params,success, error) {
def http = new HTTPBuilder( 'http://localhost:7474' )
 http.request( POST, JSON ) {
  uri.path = '/db/data/cypher/'
  headers.'X-Stream' = 'true'
  requestContentType = JSON
  body =  [ query : statement , params : params ?: [:] ]


  response.success = { resp, json ->
    if (success) success(json)
    else {
      println "Status ${resp.statusLine} Columns ${json.columns}\nData: ${json.data}"
    }
  }

  response.failure = { resp, message ->
   def result=[status:resp.statusLine.statusCode,statusText:resp.statusLine.reasonPhrase]
   result.headers = resp.headers.collect { h -> [ (h.name) : h.value ] }
   result.message = message
   if (error) {
     error(result)
   } else {
    println "Status: ${result.status} : ${result.statusText} "
    println 'Headers: ${result.headers}'
    println 'Message: ${result.message}'
    } 
  }
 }
}

query("START v=node({id}) RETURN v",[id:170],{ println "Success: ${it.data}" },{ println "Error: ${it}" })

这会返回我想要的json。所以我在grails中用控制器方法复制这个有一些麻烦,所以我选择了一个插件来执行http rest rest post请求。

所以我有一个名为CypherService的服务方法:

package awhinterface
import grails.converters.JSON
import grails.plugins.rest.client.RestBuilder

class CypherService {

 def query() {
     def rest = new RestBuilder()
     def resp = rest.post("http://localhost:7474"){
         contentType "application/json"
         body = [query: "START v=node(170) RETURN v"]

     }
     return resp as JSON;
  }
}

我为它写了一个非常简单的测试:

import grails.test.mixin.*
import org.junit.*
@TestFor(CypherService)
class CypherServiceTests {
   void testquery() {
     def cypherService = new CypherService()
     def myjson = cypherService.query()
     println(myjson)
   }
}

但是,我留下了这个错误:

Could not write request: no suitable HttpMessageConverter found for request type   [org.springframework.util.LinkedMultiValueMap] and content type [application/json]
org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.util.LinkedMultiValueMap] and content type [application/json]
at grails.plugins.rest.client.RestBuilder.doRequestInternal(RestBuilder.groovy:93)
at grails.plugins.rest.client.RestBuilder.post(RestBuilder.groovy:72)
at awhinterface.CypherService.query(CypherService.groovy:10)
at awhinterface.CypherServiceTests.testquery(CypherServiceTests.groovy:17)

我对http请求仍然很新。有人有任何煽动吗?谢谢!

修改

目前接受了一些建议并得到了这个

def query() {
    def rest = new RestBuilder()
    def resp = rest.post("http://localhost:7474") {
        contentType "application/json"
        uri = "/db/data/cypher/"
        body '{query: "START v=node(170) RETURN v"}'
    }
    return resp

出现此错误:

org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.util.LinkedMultiValueMap] and content type [application/json]
at grails.plugins.rest.client.RestBuilder.doRequestInternal(RestBuilder.groovy:93)
at grails.plugins.rest.client.RestBuilder.post(RestBuilder.groovy:72)

3 个答案:

答案 0 :(得分:3)

@ dmahapatro的答案非常接近,但您必须省略contentType设置。服务方法应如下所示:

def query( )
{
    def rest = new RestBuilder( )
    def resp = rest.post( "http://localhost:7474/db/data/cypher" ) {
        headers.'X-Stream' = 'true'
        query = "START v=node(170) RETURN id(v)"
    }
    return resp.json;
}

返回值是包含datacolumns键的地图。

旁注:要摆脱no suitable HttpMessageConverter found for request type XXX尝试添加为BuildConfig.groovy的jar依赖:

compile 'com.fasterxml.jackson.core:jackson-databind:2.2.2'

更新

如果你想使用参数化的密码,它会有点棘手。核心问题是RestBuilder在内部实例化了一个没有参数的JsonBuilder,但在这种情况下你需要参数,因为你的json现在是一个map而不是tree-ish结构。使用以下代码段进行服务:

import grails.plugins.rest.client.RestBuilder
import groovy.json.JsonBuilder

class CypherService {

def query() {
    def rest = new RestBuilder()
    def resp = rest.post( "http://localhost:7474/db/data/cypher" ) {
        headers.'X-Stream' = 'true'
        body(new JsonBuilder( query: "START v=node({nodeId}) RETURN id(v)",params: [ nodeId: 1]).toString())
    }
    return resp.json;
}

}

答案 1 :(得分:-1)

尝试使用如下:

def resp = rest.post("http://localhost:7474/db/data/cypher"){
         headers.'X-Stream' = 'true'
         contentType "application/json"

         //or
         //body '{query: "START v=node(170) RETURN v"}'

         //or [as mentioned by @codelark]
         //json query: "START v=node(170) RETURN v"

         //or
         /*json {
            query = "START v=node(170) RETURN v"
         }*/
     }

//Use resp.json instead of resp as JSON
return resp.json

RequestCustomizer对多部分请求使用setProperty,但对于jsonbody,它只是一个方法调用。

答案 2 :(得分:-1)

使用json方法代替body方法构建消息有效内容as mentioned in the documentation

def resp = rest.post("http://localhost:7474") {
    contentType "application/json"
    json query: "START v=node(170) RETURN v"
}

编辑:

可以使用body方法,但你必须在传递之前将地图数据转换为JSON

body([query: "..."] as JSON)

直接使用json会更清楚一点。