饮冰十年-人工智能-ArangoDB-02-AQL vs SQL

发布时间 2024-01-04 20:48:05作者: 逍遥小天狼

上一篇: 饮冰十年-人工智能-ArangoDB-01-初识ArangoDB

一、SQL 和 AQL

如果您使用过 MySQL、MariaDB 或 PostgreSQL 等关系数据库管理系统 (RDBMS),那么您熟悉它们的查询语言,即 SQL(结构化查询语言)。

ArangoDB 的查询语言称为 AQL(ArangoDB’ query language)。它的用途类似于 SQL。

两者都支持读取和修改数据库系统中的记录。但是,AQL 不支持数据定义操作,例如创建和删除数据库、集合和索引。

尽管数据库系统的数据模型不同,但两种语言之间还是有一些相似之处。它们是声明性语言。查询表示您想要的结果,而不是您希望如何获得结果。它们的目标是人类可读,使用英语中的关键字和读起来像句子的语法。它们还尝试独立于客户端,这意味着无论客户端使用何种编程语言或环境,所有客户端的语言和语法都是相同的。

最显着的区别可能是 AQL 中循环的概念,这使得它感觉更像是一种编程语言。AQL 一开始比普通 SQL 复杂一点,但从长远来看,它提供了更大的灵活性。它更自然地适合无架构模型,并使查询语言非常强大,同时保持易于读取和编写。

例如,SQL 的子句和 AQL 的操作是等效的,因为它们都定义了返回结果的条件。但 SQL 对查询子句使用固定顺序,确定子句在语句中必须出现的位置。在 AQL 中,操作可以以不同的顺序进行,甚至可以多次发生,从而为您提供很大的自由度。

AQL 支持复杂的查询模式,包括子查询、联接、聚合、地理空间查询、全文搜索和排名,以及图形遍历,其中一些在标准 SQL 中是有限的,甚至是不可能的。

尽管存在任何差异,但任何具有 SQL 背景的人在学习 AQL 时都应该没有困难

二、基本查询

1、INSERT 

它使用以下语法:

INSERT document INTO collection

  1.1 插入单行/文档

SQL格式:

INSERT INTO users (name, gender) VALUES ("John Doe", "m");

AQL:

INSERT { name: "John Doe", gender: "m" } INTO users

  1.2 插入多行/文档

SQL格式:

INSERT INTO users (name, gender) VALUES ("John Doe", "m"),("Jane Smith", "f");

AQL:

FOR user IN [{ name: "John Doe", gender: "m" },{ name: "Jane Smith", gender: "f" }]
  INSERT user INTO users

  1.3 从表/集合中插入行/文档

SQL格式:

INSERT INTO backup (uid, name, gender) 
  SELECT uid, name, gender FROM users WHERE active = 1;

AQL:

FOR user IN users
  FILTER user.active == 1
  INSERT user INTO backup

  1.4 生成测试行/文档

SQL格式:

使用脚本或存储过程,或者从现有表进行填充。

AQL:

FOR i IN 1..1000
  INSERT {
    name: CONCAT("test", i),
    gender: (i % 2 == 0 ? "f" : "m")
  }
  INTO users

2、UPDATE 查询

AQL 中的 UPDATE 关键字可部分修改集合中的文档。此操作有两种语法可用:

UPDATE document IN collection
UPDATE keyExpression WITH document IN collection

  2.1 更新单行/文档

SQL格式:

UPDATE users SET name = "John Smith" WHERE id = 1;

AQL:

UPDATE { _key: "1" }  WITH { name: "John Smith" }  IN users

  2.2 添加具有默认值的新列/属性

SQL格式:

ALTER TABLE users ADD COLUMN numberOfLogins INTEGER NOT NULL default 0;

AQL:

FOR user IN users UPDATE user WITH { numberOfLogins: 0 } IN users

  2.3 添加具有计算值的新列/属性

SQL格式:

ALTER TABLE users ADD COLUMN numberOfLogins INTEGER NOT NULL default 0;
UPDATE users 
SET numberOfLogins
= (SELECT COUNT(*) FROM logins WHERE user = users.id) WHERE active = 1;

AQL:

FOR user IN users
  FILTER user.active == 1
    UPDATE user 
      WITH { 
        numberOfLogins: LENGTH(
          FOR login IN logins 
            FILTER login.user == user._key 
            COLLECT WITH COUNT INTO numLogins 
            RETURN numLogins 
        )
      } IN users

  2.4 添加可选列/属性

SQL格式:不可直接实现,必须将不符合条件的行的列设置为默认值(例如 NULL)。

ALTER TABLE users 
  ADD COLUMN isImportantUser INTEGER default NULL,
  ADD COLUMN dateBecameImportant INTEGER default NULL;
 
UPDATE users 
  SET isImportantUser = 1, 
      dateBecameImportant = UNIX_TIMESTAMP()
  WHERE isImportantUser IS NULL 
AND ( SELECT COUNT(
*) FROM logins WHERE user = user.id ) > 50;

AQL:

LET date = DATE_NOW()
  FOR user IN users
    FILTER user.isImportantUser == null
    LET numberOfLogins = (
      FOR login IN logins 
        FILTER login.user == user._key
        COLLECT WITH COUNT INTO numLogins
        RETURN numLogins
      )
    FILTER numberOfLogins > 50
    UPDATE user 
      WITH { 
        isImportantUser: 1, 
        dateBecameImportant: date 
      } 
      IN users

  2.5 删除列/属性

SQL格式:

ALTER TABLE users DROP COLUMN numberOfLogins;

AQL:

FOR user IN users
  UPDATE user WITH { numberOfLogins: null } IN users 
  OPTIONS { keepNull: false }

  2.6 仅删除某些行/文档的列/属性

SQL格式:

不可直接,必须将符合条件的行的列设置为默认值(例如 NULL)。

UPDATE users SET isImportantUser = NULL, dateBecameImportant = NULL
  WHERE isImportantUser = 1 AND active = 0;

AQL:

FOR user IN users
  FILTER user.isImportantUser == 1 AND 
         user.active == 0
    UPDATE user 
      WITH { 
        isImportantUser: null, 
        dateBecameImportant: null 
      } 
      IN users 
    OPTIONS { keepNull: false }

3、REPLACE 查询

REPLACE 关键字可完全修改集合中的文档。此操作有两种语法可用:

REPLACE document IN collection
REPLACE keyExpression WITH document IN collection

  3.1 替换单行/文档

SQL格式:

REPLACE INTO users (name, gender) VALUES ("Jane Smith", "f") WHERE id = 1;

AQL:

REPLACE { _key: "1" } WITH {name: "Jane Smith", gender: "f" } IN users

  3.2 替换表/集合中的多个行/文档

SQL格式:

REPLACE INTO users (name, gender)  SELECT name, gender FROM backup;

AQL:

FOR user IN backup
  REPLACE user 
    WITH {name: backup.name, gender: backup.gender}
    IN users