专栏名称: 36大数据
关注大数据和互联网趋势,最大,最权威,最干货的大数据微信号(dashuju36)。大数据第一科技媒体。不发软文,只做知识分享。
目录
相关文章推荐
InfoTech  ·  洗个澡把offer洗没了。。 ·  2 天前  
大数据文摘  ·  1步碾压250步!何恺明新作祭出MeanFl ... ·  4 天前  
CDA数据分析师  ·  CDA数据分析人才能力模型与认证体系简介​( ... ·  4 天前  
51好读  ›  专栏  ›  36大数据

开源NoSQL数据库:ArangoDB 入门指南

36大数据  · 公众号  · 大数据  · 2017-11-08 07:50

正文

请到「今天看啥」查看全文



{
  "name": {
    "first": "Katie",
    "last": "Foster"
  }
}


INTO 必须跟在每一个 INSERT 操作后面,后面再接上我们储存文档的集合的名字。注意集合的名字不必加上引号。


如果你运行上面的查询语句,会返回一个空数组,因为你没有用 RETURN 关键词指定要返回的内容。 RETURN 关键词在修改查询中是可选项,但在数据访问查询中是必选项。就算用上 RESULT,返回值也可能是空数组,比如制定文档无法找到的情况。尽管结果为空,以上的查询仍然会创建新用户文件。你可以在文档浏览器中验证这一点。


这一次我们新建一个用户,并且让新的结果返回。


INSERT { name: "James Hendrix", age: 69 } INTO users
RETURN NEW


NEW 是一个虚拟变量,指的是用INSERT语句新建的文档。查询结果如下:


[
  {
    "_key": "10074",
    "_id": "users/10074",
    "_rev": "10074",
    "age": 69,
    "name": "James Hendrix"
  }
]


现在我们一个有三个用户了。如何用一条语句返回全部数据呢?下面的方法不起作用:


RETURN DOCUMENT("users/9883")
RETURN DOCUMENT("users/9915")
RETURN DOCUMENT("users/10074")


这里仅有一条 RETURN 语句,如果你尝试执行,则会抛出系统错误.  DOCUMENT() 函数提供了一个补充签名来指定多文档处理,所以我们可以:


RETURN DOCUMENT( ["users/9883", "users/9915", "users/10074"] )


所有3个文档的带有 _ids 的数组会被传递给函数. 数组通过方括号 [ ] 表示,而其元素使用逗号进行分隔.


但是如果我们添加更多用户会怎样呢? 我们同时需要修改查询来获取新添加的用户. 关于我们的查询,我们希望表达的是: “对于 users 集合中的每一个用户, 返回用户文档”. 我们可以使用 FOR 循环格式化该查询:


FOR user IN users
  RETURN user


它表达的是对 users 中的所有文档进行迭代并使用user 作为变量名, 从而我们可以用来指代当前用户文档. 它可以被称为 doc, u 或 ahuacatlguacamole, 这取决于你. 然而建议使用一个简短并自描述的名字.


循环体告诉系统返回变量 user 的值, 这是一个用户文档. 可以像下面这样返回所有用户文档:


[
  {
    "_key": "9915",
    "_id": "users/9915",
    "_rev": "9915",
    "age": 27,
    "name": "Katie Foster"
  },
  {
    "_key": "9883",
    "_id": "users/9883",
    "_rev": "9883",
    "age": 32,
    "name": "John Smith"
  },
  {
    "_key": "10074",
    "_id": "users/10074",
    "_rev": "10074",
    "age": 69,
    "name": "James Hendrix"
  }
]


也许你已经注意到返回的文档顺序与插入顺序并不相同. ArangoDB 并不保证文档顺序,除非你显式对其进行排序. 我们可以很容易添加了一个 SORT 操作:


FOR user IN users
  SORT user._key
  RETURN user


这依然不会返回预期的结果: James (10074) 会在 John (9883) 与 Katie (9915) 之前返回. 原因在于 _key 属性在 ArangoDB 中是一个字符串,而不是一个数字. 字符串的单个字符会被进行比较. 1 小于 9 ,因而结果是 “正确”的. 如果我们希望使用数值作为 _key 属性的值,我们可以将字符串转换为数字并用其进行排序. 然而这样做有一些影响T. 我们最好排序其他内容. 年龄怎么样?以降序排列吗?


FOR user IN users
  SORT user.age DESC
  RETURN user


用户的数据会以如下的顺序返回: James (69), John (32), Katie (27)。与用DESC返回降序结果不同, ASC返回升序结果。 ASC是默认的选项,可以省略。


我们可能需要根据用户的年龄返回一个子集。让我们返回30岁以上的用户的数据:


FOR user IN users
  FILTER user.age > 30
  SORT user.age
  RETURN user


这么做会按顺序返回John and James。 Katie’s age的属性不满足三十岁以上的条件,她只有27岁,因此不再结果之中。我们可以修改她的年龄,使她重新包含在返回结果之中,使用如下的查询语句:


UPDATE "9915" WITH { age: 40 } IN users
RETURN NEW


UPDATE 允许部分编辑已存在的文档. 另外有 REPLACE, 会移除所有属性 (除了 _key 与 _id 保持不变) 并且仅添加部分属性. 另一方面 UPDATE 替换指定的属性而保持其他属性不变.


UPDATE 关键字后跟文档键 (或者带有 _key 属性的文档 / 对象) 来指定要修改的文档. 要更新的属性作为对象使用 WITH关键字写入. IN 表示在哪个集合中执行该操作, 类似 INTO (这里两个关键字可以互换). 如果我们使用 NEW 伪变量则会返回应用修改的全部文档:


[
  {
    "_key": "9915",
    "_id": "users/9915",
    "_rev": "12864",
    "age": 40,
    "name": "Katie Foster"
  }


相反如果我们使用 REPLACE , name 属性会丢失. 使用 UPDATE, 属性会被保留 (如果我们有其他的属性,也同样适用该规则).


让我们再次运行 FILTER 查询, 但是这一次仅返回用户名:


FOR user IN users
  FILTER user.age > 30
  SORT user.age
  RETURN user.name


这会返回所有3个用户的名字:


[
  "John Smith",
  "Katie Foster",
  "James Hendrix"
]


如果仅返回一个属性的子集,则将其称为投影. 另一种投影类型是改变结果的结构:


FOR user IN users
  RETURN { userName: user.name, age: user.age }


该查询为所有的用户文档定义了输出格式. 用户名作为 userName 返回,而不是 name, 在该示例中 age 与属性性键相同:


[
  {
    "userName": "James Hendrix",
    "age": 69
  },
  {
    "userName": "John Smith",
    "age": 32
  },
  {
    "userName": "Katie Foster",
    "age": 40
  }
]


也可以计算新值:


FOR user IN users
  RETURN CONCAT(user.name, "'s age is ", user.age)


CONCAT() 是一个将元素合并为字符串的函数. 在这里我们用其为所有用户返回一个描述. 正如你看到的,结果集合并不总是一个对象数组:


[
  "James Hendrix's age is 69",
  "John Smith's age is 32",
  "Katie Foster's age is 40"
]


现在让我们来做一些疯狂的事情: 对于用户集合中的所有文档,再次对所有用户文档进行迭代并返回用户组合,例如 John 与 Katie. 对于该问题,我们可以在一个循环内部使用一个循环来获得叉积 (所有用户记录的所有可能组合, 3 3 = 9). 然而我们并不希望得到类似 John + John* 的组合, 所以让我们使用一个过滤器条件来去除类似的组合:


FOR user1 IN users
  FOR user2 IN users
    FILTER user1 != user2
    RETURN [user1.name, user2.name]


我们得到6对组合。类似 James + John 与 John + James 的组合是重复的,但是已足够好:


[
  [ "James Hendrix", "John Smith" ],
  [ "James Hendrix", "Katie Foster" ],
  [ "John Smith", "James Hendrix" ],
  [ "John Smith", "Katie Foster" ],
  [ "Katie Foster", "James Hendrix" ],
  [ "Katie Foster", "John Smith" ]
]


我们可以像下面这样计算两个年龄之和并计算一些新的内容:


FOR user1 IN users
  FOR user2 IN users
    FILTER user1 != user2
    RETURN {
        pair: [user1.name, user2.name],
        sumOfAges: user1.age + user2.age
    }


我们引入一个新的属性 sumOfAges 并将两个年龄相加作为其值:


[
  {
    "pair": [ "James Hendrix", "John Smith" ],
    "sumOfAges": 101
  },
  {
    "pair": [ "James Hendrix", "Katie Foster" ],
    "sumOfAges": 109
  },
  {
    "pair": [ "John Smith", "James Hendrix" ],
    "sumOfAges": 101
  },
  {
    "pair": [ "John Smith", "Katie Foster" ],
    "sumOfAges": 72
  },
  {
    "pair": [ "Katie Foster", "James Hendrix" ],
    "sumOfAges": 109
  },
  {
    "pair": [ "Katie Foster", "John Smith" ],
    "sumOfAges": 72
  }
]


如果我们希望过滤新属性来仅返回总和小于100的组合,我们应该定义一个变量来临时存储总和,从而我们可以在 FILTER 语句以及 RETURN 语句中使用:


FOR user1 IN users
  FOR user2 IN users
    FILTER user1 != user2
    LET sumOfAges = user1.age + user2.age
    FILTER sumOfAges < 100
    RETURN {
        pair: [user1.name, user2.name],
        sumOfAges: sumOfAges
    }








请到「今天看啥」查看全文