【问题标题】:Orientdb NoSQL conditionally execute a queryOrientdb NoSQL 有条件地执行查询
【发布时间】:2018-04-20 02:44:24
【问题描述】:

我正在使用 OrientDB REST API 并试图找到一种方法来检查边缘并在它不存在时仅使用一个 POST 请求来创建它。多个查询和命令都可以,只是想尽量减少与服务器来回产生的开销。

我已经编写了一个查询来检查 OrientDB 内置的 Tolkien-Arda 数据集中的边缘:

SELECT IF(COUNT(*) FROM 
(SELECT FROM Begets
WHERE OUT IN (SELECT FROM Creature WHERE uniquename='rosaBaggins') 
AND IN IN (SELECT FROM Creature WHERE uniquename='adalgrimTook')) > 0, "True", "False")

这个丑陋的查询怪物只计算从 rosaBaggins 到 adalgrimTook 的边数,如果返回大于 0 则返回“true”,否则返回 false。

但是,如果为 true,我不确定如何进行下一步并执行 CREATE EDGE 查询。对此或更有效地编写我疯狂的查询的帮助表示赞赏,我觉得我已经完成了艰难的道路。

【问题讨论】:

    标签: nosql orientdb orientdb2.2


    【解决方案1】:

    如果您愿意,可以通过 Java API 执行此操作,此代码检查是否存在从 rosaBaggins 到 adalgrimTook 的传出边:

    String DB = "<db name>";
    String path = "remote:localhost/" + DB;
    OServerAdmin serverAdmin;
    
    try
    {
        serverAdmin = new OServerAdmin(path).connect("<username>", "<password>");
        if(serverAdmin.existsDatabase())
        {
            OrientGraphFactory factory = new OrientGraphFactory(path);
            OrientGraph g = factory.getTx();
    
            Iterable<Vertex> result = g.command(new OCommandSQL("SELECT FROM #18:0 WHERE out().uniquename contains 'adalgrimTook'")).execute();
            List<Vertex> list = new ArrayList<Vertex>();
            CollectionUtils.addAll(list, result.iterator());
    
            if(list.size() == 0)
            {
                System.out.println("Edge doesn't exist, I'm creating it ...");
                g.command(new OCommandSQL("CREATE EDGE connection FROM (SELECT FROM Creature WHERE uniquename = 'rosaBaggins') TO (SELECT FROM Creature WHERE uniquename = 'adalgrimTook')")).execute();
            }
            else
            {
                System.out.println("Edge already exist");
            }
    
            serverAdmin.close();
        }
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
    

    希望对你有帮助

    问候

    【讨论】:

      【解决方案2】:

      由于没有提到它是用 Java 编写的,我将只为您提供这个边缘 Upsert 的纯 SQL 实现

      let $1 = select from user where _id = 'x5mxEBwhMfiLSQHaK';
      let $2 = select expand(both('user_story')) from story where _id = '5ab4ddea1908792c6aa06a93';
      let $3 = select intersect($1, $2);
      if($3.size() > 0) {
        return 'already inserted';
      }
      create edge user_story from (select from user where _id = 'x5mxEBwhMfiLSQHaK') to (select from story where _id = '5ab4ddea1908792c6aa06a93')
      return 'just inserted';
      

      我没有使用来自 tolkien-Arda 的原始代码,但请随意填写该代码。

      结构由用户和他编写的故事组成。如果它们尚未链接,则会创建一条边 (user_story)。

      【讨论】:

      • 感谢您的回复,但是 if 语句给出了错误“找不到命令请求的命令执行器”。据我所知,if 语句只能用于返回值,不能用于查询,这是我遇到的问题。
      • 您确定命令是作为批处理输入的吗?在 orientdb studio 中,您可以使用命令窗口下的选项图标来执行此操作。将 SQL 更改为批处理。
      【解决方案3】:

      使用@mitchken 的部分答案,我已经弄清楚了。

      LET $1 = SELECT expand(bothE('Begets')) from Creature where uniquename='asdfasdf';\
      LET $2 = SELECT expand(bothE('Begets')) FROM Creature WHERE uniquename='adalgrimTook';\
      LET $3 = SELECT INTERSECT($1, $2);\
      LET $4 = CREATE EDGE Begets FROM (SELECT FROM Creature WHERE uniquename='asdfasdf') TO (SELECT FROM Creature WHERE uniquename='adalgrimTook');\
      SELECT IF($3.INTERSECT.size() > 0, 'Already exists', $4)
      

      第一次将此脚本发送到服务器会在“asdfasdf”(我刚刚创建的一个顶点)和“adalgrimTook”之间创建一条新边,并返回新边的@rid。我第二次将脚本发送到服务器时,它返回“已经存在”。

      另外需要注意的是(让我很沮丧地弄清楚这一点)是 LET 语句在 CLI 或 Web GUI 上的“浏览”选项卡中不起作用,但作为 POST 脚本可以正常工作。

      【讨论】:

      • 只有在批处理模式下,它们才会在 GUI 中运行。
      • 这个脚本每次都会尝试创建一个,所以对我来说似乎不是一个解决方案。除非您的边缘在进出上都是独一无二的,但这会使其返回错误。
      猜你喜欢
      • 2019-09-12
      • 1970-01-01
      • 2021-01-18
      • 1970-01-01
      • 2013-06-16
      • 2016-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多