构建API以访问Neo4j数据

时间:2016-01-27 20:11:00

标签: neo4j

我使用批量导入工具创建了一个巨大的Neo4j数据库。现在,我想通过API(将在后端运行查询)向我的用户公开数据的某些部分。我的要求非常普遍:
1.延迟应该是最小的 2.支持约10-20的qps。

有人可以就我应该使用的内容以及有关如何进行此操作的任何文档向我提出建议吗?我看到了几个ruby / rails和REST API的例子 - 但是它们特定于在后端没有任何复杂查询的情况下公开数据。我不知道如何将其转换为我想要的特定API。任何帮助将不胜感激。

感谢。

4 个答案:

答案 0 :(得分:1)

我写了一个简单的Flask API示例,它与Neo4j接口,用于简单演示(用于消息传递iOS应用程序的后端)。

您可能会发现它是一个有用的参考:https://github.com/johnymontana/messages-api

还有一些资源可以在线使用Flask和Neo4j:

答案 1 :(得分:1)

查看GraphAware Framework。您可以直接在Neo4j(相同的JVM)上构建API,但您必须使用Cypher,Java或Scala。

我从Cypher开始,因为您可以非常快速地编写它,然后针对性能进行优化,最后,如果所有其他方法都失败并且您的延迟仍然很高,则转换为Java。

您可以非常轻松地暴露子图(或甚至部分水合的节点和关系,即仅某些属性)。查看api包中的内容。示例代码:

你会写一个控制器来返回一个人的图表,但只包括节点的名字(不是年龄或其他任何东西):

@RestController
public class ApiExample {

    private final GraphDatabaseService database;

    @Autowired
    public ApiExample(GraphDatabaseService database) {
        this.database = database;
    }

    @RequestMapping(path = "person/{name}")
    public JsonGraph getPersonGraph(@PathVariable(value = "name") String name) {
        JsonGraph<?> result = new JsonGraph() {
            @Override
            protected JsonGraph self() {
                return this;
            }
        };

        try (Transaction tx = database.beginTx()) {
            Node person = database.findNode(label("Person"), "name", name);

            if (person == null) {
                throw new NotFoundException(); //eventually translate to 404
            }

            result.addNode(person, IncludeOnlyNameNodeTransformer.INSTANCE);

            for (Relationship worksFor : person.getRelationships(withName("WORKS_FOR"), Direction.OUTGOING)) {
                result.addRelationship(worksFor);
                result.addNode(worksFor.getEndNode(), IncludeOnlyNameNodeTransformer.INSTANCE);
            }

            tx.success();
        }

        return result;
    }

    private static final class IncludeOnlyNameNodeTransformer implements NodeTransformer<LongIdJsonNode> {

        private static final IncludeOnlyNameNodeTransformer INSTANCE = new IncludeOnlyNameNodeTransformer();

        private IncludeOnlyNameNodeTransformer() {
        }

        @Override
        public LongIdJsonNode transform(Node node) {
            return new LongIdJsonNode(node, new String[]{"name"});
        }
    }
}

运行此测试

public class ApiExampleTest extends GraphAwareApiTest {

    @Override
    protected void populateDatabase(GraphDatabaseService database) {
        database.execute("CREATE INDEX ON :Person(name)");
        database.execute("CREATE (:Person {name:'Michal', age:32})-[:WORKS_FOR {since:2013}]->(:Company {name:'GraphAware', est:2013})");
    }

    @Test
    public void testExample() {
        System.out.println(httpClient.get(baseUrl() + "/person/Michal/", 200));
    }
}

将返回以下JSON

{
  "nodes": [
    {
      "properties": {
        "name": "GraphAware"
      },
      "labels": [
        "Company"
      ],
      "id": 1
    },
    {
      "properties": {
        "name": "Michal"
      },
      "labels": [
        "Person"
      ],
      "id": 0
    }
  ],
  "relationships": [
    {
      "properties": {
        "since": 2013
      },
      "type": "WORKS_FOR",
      "id": 0,
      "startNodeId": 0,
      "endNodeId": 1
    }
  ]
}

答案 2 :(得分:0)

显然你可以使用像Rails / Sinatra这样的框架来自己动手。如果您想要API格式化的标准,我非常喜欢JSON API标准:

http://jsonapi.org/

以下是The Changelog播客的一集,谈论它:

https://changelog.com/189/

还有一个用于创建资源对象的gem,用于确定暴露的内容和不暴露的内容:

https://github.com/cerebris/jsonapi-resources

我使用neo4j gem尝试了一下它并且它在基本级别工作,但是一旦你开始进入include,似乎有一些依赖于ActiveRecord。不过,我很乐意看到这样的问题。

您还可以查看由Facebook创建的GraphQL标准:

https://github.com/facebook/graphql

它有一个Ruby宝石:

https://github.com/rmosolgo/graphql-ruby

当然还有另一集The Changelog;)

http://5by5.tv/changelog/149

Ruby的各种其他API资源:

https://github.com/webmachine/webmachine-ruby https://github.com/ruby-grape/grape

答案 3 :(得分:0)

使用grest

您可以简单地定义主要模型及其关系(作为次要模型),并尽可能快地使用最少的编码构建API!