内容简介:ArangoDB查询语言(AQL)类似于结构化查询语言(SQL) 在它的目的。两者都支持读取和修改集合数据,但AQL不支持数据定义操作,例如创建和删除数据库,集合和索引。
ArangoDB查询语言(AQL)类似于结构化查询语言(SQL) 在它的目的。两者都支持读取和修改集合数据,但AQL不支持数据定义操作,例如创建和删除数据库,集合和索引。
虽然有些关键字重叠,但AQL语法与 SQL 不同。例如,SQL WHERE和AQL FILTER子句是等效的,因为它们都定义了返回结果的条件。但是,SQL使用预定义的序列来确定WHERE语句必须在哪里出现。在AQL中,子句从左到右执行,因此FILTER查询中子句的位置决定了它的优先级。
尽管有这些差异,任何具有SQL背景的人都应该没有学习AQL的困难。
一、数据预览
本次使用的数据共有43条,每条数据包含姓氏、年龄、活动状态和特征等六个字段
其中每个特征都有一个随机字母作为文档密钥。特质标签有英文和德文。
地点由地名和经纬度组成:
二、基本的CRUD
创建集合:
在创建文档之前,需要创造一个放置它的集合,集合可以通过Web界面,arangosh或驱动程序来创建。AQL无法创建集合。
单击Web界面中的COLLECTIONS,然后单击Add Collection并键入 Charactersname。使用保存确认。新集合就出现在了列表中。
插入单个对象:
使用AQL插入文档
INSERT {
"name": "Ned",
"surname": "Stark",
"alive": true,
"age": 41,
"traits": ["A","H","C","N","P"]
} INTO Characters
复制代码
语法:
INSERT document INTO collectionName
该文档是一个对象,由属性键和值对组成。属性键的引号在AQL中是可选的。键总是字符串,而属性值可以有不同的类型:
- null
- boolean (true, false)
- number (integer and floating point)
- string
- array
- object
批量插入对象:
AQL不允许INSERT在单个查询中针对同一集合的多个操作。但是可以使用FOR循环体,插入多个文档。
LET data = [
{ "name": "Robert", "surname": "Baratheon", "alive": false, "traits": ["A","H","C"] },
{ "name": "Jaime", "surname": "Lannister", "alive": true, "age": 36, "traits": ["A","F","B"] },
{ "name": "Catelyn", "surname": "Stark", "alive": false, "age": 40, "traits": ["D","H","C"] },
{ "name": "Cersei", "surname": "Lannister", "alive": true, "age": 36, "traits": ["H","E","F"] },
{ "name": "Daenerys", "surname": "Targaryen", "alive": true, "age": 16, "traits": ["D","H","C"] },
{ "name": "Jorah", "surname": "Mormont", "alive": false, "traits": ["A","B","C","F"] },
{ "name": "Petyr", "surname": "Baelish", "alive": false, "traits": ["E","G","F"] },
{ "name": "Viserys", "surname": "Targaryen", "alive": false, "traits": ["O","L","N"] },
{ "name": "Jon", "surname": "Snow", "alive": true, "age": 16, "traits": ["A","B","C","F"] },
{ "name": "Sansa", "surname": "Stark", "alive": true, "age": 13, "traits": ["D","I","J"] },
{ "name": "Arya", "surname": "Stark", "alive": true, "age": 11, "traits": ["C","K","L"] },
{ "name": "Robb", "surname": "Stark", "alive": false, "traits": ["A","B","C","K"] },
{ "name": "Theon", "surname": "Greyjoy", "alive": true, "age": 16, "traits": ["E","R","K"] },
{ "name": "Bran", "surname": "Stark", "alive": true, "age": 10, "traits": ["L","J"] },
{ "name": "Joffrey", "surname": "Baratheon", "alive": false, "age": 19, "traits": ["I","L","O"] },
{ "name": "Sandor", "surname": "Clegane", "alive": true, "traits": ["A","P","K","F"] },
{ "name": "Tyrion", "surname": "Lannister", "alive": true, "age": 32, "traits": ["F","K","M","N"] },
{ "name": "Khal", "surname": "Drogo", "alive": false, "traits": ["A","C","O","P"] },
{ "name": "Tywin", "surname": "Lannister", "alive": false, "traits": ["O","M","H","F"] },
{ "name": "Davos", "surname": "Seaworth", "alive": true, "age": 49, "traits": ["C","K","P","F"] },
{ "name": "Samwell", "surname": "Tarly", "alive": true, "age": 17, "traits": ["C","L","I"] },
{ "name": "Stannis", "surname": "Baratheon", "alive": false, "traits": ["H","O","P","M"] },
{ "name": "Melisandre", "alive": true, "traits": ["G","E","H"] },
{ "name": "Margaery", "surname": "Tyrell", "alive": false, "traits": ["M","D","B"] },
{ "name": "Jeor", "surname": "Mormont", "alive": false, "traits": ["C","H","M","P"] },
{ "name": "Bronn", "alive": true, "traits": ["K","E","C"] },
{ "name": "Varys", "alive": true, "traits": ["M","F","N","E"] },
{ "name": "Shae", "alive": false, "traits": ["M","D","G"] },
{ "name": "Talisa", "surname": "Maegyr", "alive": false, "traits": ["D","C","B"] },
{ "name": "Gendry", "alive": false, "traits": ["K","C","A"] },
{ "name": "Ygritte", "alive": false, "traits": ["A","P","K"] },
{ "name": "Tormund", "surname": "Giantsbane", "alive": true, "traits": ["C","P","A","I"] },
{ "name": "Gilly", "alive": true, "traits": ["L","J"] },
{ "name": "Brienne", "surname": "Tarth", "alive": true, "age": 32, "traits": ["P","C","A","K"] },
{ "name": "Ramsay", "surname": "Bolton", "alive": true, "traits": ["E","O","G","A"] },
{ "name": "Ellaria", "surname": "Sand", "alive": true, "traits": ["P","O","A","E"] },
{ "name": "Daario", "surname": "Naharis", "alive": true, "traits": ["K","P","A"] },
{ "name": "Missandei", "alive": true, "traits": ["D","L","C","M"] },
{ "name": "Tommen", "surname": "Baratheon", "alive": true, "traits": ["I","L","B"] },
{ "name": "Jaqen", "surname": "H'ghar", "alive": true, "traits": ["H","F","K"] },
{ "name": "Roose", "surname": "Bolton", "alive": true, "traits": ["H","E","F","A"] },
{ "name": "The High Sparrow", "alive": true, "traits": ["H","M","F","O"] }
]
FOR d IN data
INSERT d INTO Characters
复制代码
语法:
LET variableName = valueExpression
LET关键字定义了同名称的变量数据和对象值的数列,格式为 [ {...}, {...}, ... ]
FOR variableName IN expression
用于迭代数据数组的每个元素 。在每个循环中,将一个元素分配给变量d。然后在INSERT语句中使用此变量。相当于下面的格式:
INSERT {
"name": "Robert",
"surname": "Baratheon",
"alive": false,
"traits": ["A","H","C"]
} INTO Characters
INSERT {
"name": "Jaime",
"surname": "Lannister",
"alive": true,
"age": 36,
"traits": ["A","F","B"]
} INTO Characters
...
复制代码
检索
检索集合中的所有文档:
FOR c IN Characters
RETURN c
复制代码
语法:
FOR variableName IN collectionName
对于集合中的每个文档,依次分配给变量c,然后根据循环体返回该文档。
选取其中一个文档如下:
{
"_key": "2861650",
"_id": "Characters/2861650",
"_rev": "_V1bzsXa---",
"name": "Ned",
"surname": "Stark",
"alive": true,
"age": 41,
"traits": ["A","H","C","N","P"]
},
复制代码
该文档包含我们存储的四个属性,以及数据库系统添加的另外三个属性:
-
_key:文档键,用户可以在创建文档时提供文档键,也可以自动分配唯一值,不能改变,只读
-
_id:集合名/文档键,只读
-
_rev:系统管理的修订版ID,只读
检索特定文档:
RETURN DOCUMENT("Characters", "2861650")
// --- or ---
RETURN DOCUMENT("Characters/2861650")
复制代码
返回:
[
{
"_key": "2861650",
"_id": "Characters/2861650",
"_rev": "_V1bzsXa---",
"name": "Ned",
"surname": "Stark",
"alive": true,
"age": 41,
"traits": ["A","H","C","N","P"]
}
]
复制代码
语法:
DOCUMENT()
使用_key或_id检索特定文档,该函数还允许一次获取多个文档
RETURN DOCUMENT("Characters", ["2861650", "2861653"])
// --- or ---
RETURN DOCUMENT(["Characters/2861650", "Characters/2861653"])
复制代码
更新文档:
修改现有文件:
UPDATE "2861650" WITH { alive: false } IN Characters
语法:
UPDATE documentKey WITH object IN collectionName
复制代码
用列出的属性更新指定的文档(如果它们不存在则添加它们),但保持其余不变。要替换整个文档内容,则要使用REPLACE函数:
REPLACE "2861650" WITH {
name: "Ned",
surname: "Stark",
alive: false,
age: 41,
traits: ["A","H","C","N","P"]
} IN Characters
复制代码
该函数也适用于循环,例如为所有文档添加新属性:
FOR c IN Characters
UPDATE c WITH { season: 1 } IN Characters
复制代码
删除文件:
语法:
REMOVE _key IN Collectiosname
要从集合中完全删除文档,需要执行REMOVE操作。它的工作方式与其他修改操作类似,但没有WITH子句:
REMOVE "2861650" IN Characters 复制代码
三、匹配文件
语法:
FILTER
查找满足比_key相等更复杂的条件的文档,能够为要匹配的文档制定任意条件。
等于条件:
FOR c IN Characters
FILTER c.name == "Ned"
RETURN c
复制代码
过滤条件如下:“ 字符文档的属性name必须等于字符串Ned ”。如果条件适用,则返回字符文档。
范围条件:
FOR c IN Characters
FILTER c.age >= 13
RETURN c.name
复制代码
多种条件:
FOR c IN Characters
FILTER c.age < 13
FILTER c.age != null
RETURN { name: c.name, age: c.age }
//or
FOR c IN Characters
FILTER c.age < 13 AND c.age != null
RETURN { name: c.name, age: c.age }
复制代码
替代条件:
FOR c IN Characters
FILTER c.name == "Jon" OR c.name == "Joffrey"
RETURN { name: c.name, surname: c.surname }
复制代码
四、 排序 和限制
限制语法:
LIMIT()
LIMIT后面跟着一个最大显示数的数字,限制结果显示行数。
FOR c IN Characters
LIMIT 5
RETURN c.name
复制代码
还可以使用LIMIT来跳过一定数量的记录返回下一个n个文档:
FOR c IN Characters
LIMIT 2, 5
RETURN c.name
复制代码
排序语法:
SORT()
DESC降序来反转排序顺序
FOR c IN Characters
SORT c.name DESC
LIMIT 10
RETURN c.name
复制代码
多个字段排序
FOR c IN Characters
FILTER c.surname
SORT c.surname, c.name
LIMIT 10
RETURN {
surname: c.surname,
name: c.name
}
复制代码
此处FILTER的作用是仅保留surname为非空记录
五、组合
语法: MERGE()
MERGE()的功能是将对象组合在一起。因为使用了原始字符属性{ traits: ... },所以后者被合并覆盖。
FOR c IN Characters
RETURN MERGE(c, { traits: DOCUMENT("Traits", c.traits)[*].en } )
复制代码
六、图操作
创建图:
语法:
INSERT { _from: _id(A), _to: _id(B) } INTO ChildOf
实例: 首先,创建一个新的集合,并确保将集合类型更改为Edge。
然后,通过查询多个集合的数据,将结果存入边集合中
LET data = [ //关系数据
{
"parent": { "name": "Ned", "surname": "Stark" },
"child": { "name": "Robb", "surname": "Stark" }
}, {
"parent": { "name": "Ned", "surname": "Stark" },
"child": { "name": "Sansa", "surname": "Stark" }
}, {
"parent": { "name": "Ned", "surname": "Stark" },
"child": { "name": "Arya", "surname": "Stark" }
}, {
"parent": { "name": "Ned", "surname": "Stark" },
"child": { "name": "Bran", "surname": "Stark" }
}, {
"parent": { "name": "Catelyn", "surname": "Stark" },
"child": { "name": "Robb", "surname": "Stark" }
}, {
"parent": { "name": "Catelyn", "surname": "Stark" },
"child": { "name": "Sansa", "surname": "Stark" }
}, {
"parent": { "name": "Catelyn", "surname": "Stark" },
"child": { "name": "Arya", "surname": "Stark" }
}, {
"parent": { "name": "Catelyn", "surname": "Stark" },
"child": { "name": "Bran", "surname": "Stark" }
}, {
"parent": { "name": "Ned", "surname": "Stark" },
"child": { "name": "Jon", "surname": "Snow" }
}, {
"parent": { "name": "Tywin", "surname": "Lannister" },
"child": { "name": "Jaime", "surname": "Lannister" }
}, {
"parent": { "name": "Tywin", "surname": "Lannister" },
"child": { "name": "Cersei", "surname": "Lannister" }
}, {
"parent": { "name": "Tywin", "surname": "Lannister" },
"child": { "name": "Tyrion", "surname": "Lannister" }
}, {
"parent": { "name": "Cersei", "surname": "Lannister" },
"child": { "name": "Joffrey", "surname": "Baratheon" }
}, {
"parent": { "name": "Jaime", "surname": "Lannister" },
"child": { "name": "Joffrey", "surname": "Baratheon" }
}
]
FOR rel in data
LET parentId = FIRST( //FIRST()提取第一个元素
FOR c IN Characters
FILTER c.name == rel.parent.name //筛选条件
FILTER c.surname == rel.parent.surname
LIMIT 1
RETURN c._id //返回_id
)
LET childId = FIRST(
FOR c IN Characters
FILTER c.name == rel.child.name
FILTER c.surname == rel.child.surname
LIMIT 1
RETURN c._id
)
FILTER parentId != null AND childId != null //剔除_id都为空的记录
INSERT { _from: childId, _to: parentId } INTO ChildOf //将数据插入边集合
RETURN NEW //返回数据
复制代码
也可以直接创建边数据:
INSERT { _from: "Characters/robb", _to: "Characters/ned" } INTO ChildOf
复制代码
遍历图:
语法:
FOR v IN 1..1 OUTBOUND _id ChildOf
RETURN v.name
其中1..1为遍历深度
复制代码
实例:
FOR c IN Characters
FILTER c.name == "Bran"
FOR v IN 1..1 OUTBOUND c ChildOf
RETURN v.name
复制代码
返回
[ "Ned", "Catelyn" ] 复制代码
遍历的情况如下图:
若是反向遍历,则需要使用到INBOUND关键字:
FOR c IN Characters
FILTER c.name == "Tywin"
FOR v IN 2..2 INBOUND c ChildOf
RETURN DISTINCT v.name
输出:
[
"Joffrey"
]
复制代码
遍历情况如下:
需要注意的是,“1..1”限制了遍历深度为1,“2..2”限制了遍历深度为2,而"1..2"限制遍历深度既可以为1也可以为2。
七、地理空间查询
地点数据
创建地点集合:
录入地点数据:
LET places = [
{ "name": "Dragonstone", "coordinate": [ 55.167801, -6.815096 ] },
{ "name": "King's Landing", "coordinate": [ 42.639752, 18.110189 ] },
{ "name": "The Red Keep", "coordinate": [ 35.896447, 14.446442 ] },
{ "name": "Yunkai", "coordinate": [ 31.046642, -7.129532 ] },
{ "name": "Astapor", "coordinate": [ 31.50974, -9.774249 ] },
{ "name": "Winterfell", "coordinate": [ 54.368321, -5.581312 ] },
{ "name": "Vaes Dothrak", "coordinate": [ 54.16776, -6.096125 ] },
{ "name": "Beyond the wall", "coordinate": [ 64.265473, -21.094093 ] }
]
FOR place IN places
INSERT place INTO Locations
复制代码
设置地理空间索引:
在COLLECTIONS界面,添加新的Indexes,设置为coordinate字段:
查找附近的位置
语法:
NEAR()
找到最接近的坐标参考点
FOR loc IN NEAR(Locations, 53.35, -6.26, 3)
RETURN {
name: loc.name,
latitude: loc.coordinate[0],
longitude: loc.coordinate[1]
}
复制代码
输出:
[
{
"name": "Vaes Dothrak",
"latitude": 54.16776,
"longitude": -6.096125
},
{
"name": "Winterfell",
"latitude": 54.368321,
"longitude": -5.581312
},
{
"name": "Dragonstone",
"latitude": 55.167801,
"longitude": -6.815096
}
]
复制代码
查找半径内的位置
语法:
WITHIN()
从参考点搜索给定半径内的位置
FOR loc IN WITHIN(Locations, 53.35, -6.26, 200 * 1000)
RETURN {
name: loc.name,
latitude: loc.coordinate[0],
longitude: loc.coordinate[1]
}
复制代码
输出
[
{
"name": "Vaes Dothrak",
"latitude": 54.16776,
"longitude": -6.096125
},
{
"name": "Winterfell",
"latitude": 54.368321,
"longitude": -5.581312
}
]
复制代码
按距离查找位置:
语法:
NEAR()或WITHIN()
通过添加一个可选的第五个参数返回到参考点的距离。必须是一个字符串:
FOR loc IN NEAR(Locations, 53.35, -6.26, 3, "distance")
RETURN {
name: loc.name,
latitude: loc.coordinate[0],
longitude: loc.coordinate[1],
distance: loc.distance / 1000
}
复制代码
输出:
[
{
"name": "Vaes Dothrak",
"latitude": 54.16776,
"longitude": -6.096125,
"distance": 91.56658640314431
},
{
"name": "Winterfell",
"latitude": 54.368321,
"longitude": -5.581312,
"distance": 121.66399816395028
},
{
"name": "Dragonstone",
"latitude": 55.167801,
"longitude": -6.815096,
"distance": 205.31879386198324
}
]
复制代码
以上所述就是小编给大家介绍的《ArangoDB查询语言(AQL) 基本语法&用法》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Flutter语法(1):extends 、 implements 、 with的用法与区别
- Python爬虫利器三之Xpath语法与lxml库的用法
- Swift语法快速入门(一)之 Swift基础语法
- 在ES6中使用扩展语法有什么好处?它与rest语法有什么不同?
- AWK 的用法
- AWK基础用法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Release It!
Michael T. Nygard / Pragmatic Bookshelf / 2007-03-30 / USD 34.95
“Feature complete” is not the same as “production ready.” Whether it’s in Java, .NET, or Ruby on Rails, getting your application ready to ship is only half the battle. Did you design your system to......一起来看看 《Release It!》 这本书的介绍吧!