我正在尝试使用ArangoDB来获取朋友的朋友列表.不仅仅是一个基本的朋友朋友列表,我还想知道用户和朋友的朋友有多少朋友,并对结果进行排序.在多次尝试(重新)编写性能最佳的AQL查询之后,这就是我最终的结果:
LET friends = (
FOR f IN GRAPH_NEIGHBORS('graph', @user, {"direction": "any", "includeData": true, "edgeExamples": { name: "FRIENDS_WITH"}})
RETURN f._id
)
LET foafs = (FOR friend IN friends
FOR foaf in GRAPH_NEIGHBORS('graph', friend, {"direction": "any", "includeData": true, "edgeExamples": { name: "FRIENDS_WITH"}})
FILTER foaf._id != @user AND foaf._id NOT IN friends
COLLECT foaf_result = foaf WITH COUNT INTO common_friend_count
RETURN {
user: foaf_result,
common_friend_count: common_friend_count
}
)
FOR foaf IN foafs
SORT foaf.common_friend_count DESC
RETURN foaf
Run Code Online (Sandbox Code Playgroud)
不幸的是,性能并不像我想的那么好.与同一查询(和数据)的Neo4j版本相比,AQL似乎相当慢(5-10倍).
我想知道的是......我如何改进查询以使其表现更好?
我主要打算问这个问题:"ArangoDB是真正的图形数据库吗?"
但是,这个问题听起来很冒犯.
你们,triAGENS的人们在创建"多范式"数据库方面做得非常出色.作为PostgreSQL,PostGIS,MongoDB和Neo4J/Titan的用户,我真的很高兴看到"一体化"的解决方案:)
但问题仍然存在,基本上在ArangoDB中创建图形需要创建两个独立的集合:一个用于边缘,一个用于顶点,因此,据我所知,它已经意味着顶点和相关边缘不是"物理"邻居.
而且,即使在创建了适当的索引之后,我在Gremlin中做这种事情时也面临着一些严重的性能问题
g.v('an_id').out('likes').in('likes').count()
Run Code Online (Sandbox Code Playgroud)
在~3秒后(感知时间)返回结果
我以为我很难理解Gremlin和Blueprint/ArangoDB是如何工作的所以我试图用AQL重写相同的查询:
LET lst = (FOR e1 in NEIGHBORS(vertices, edges, "an_id", "outbound", [ { "$label": "likes" } ] )
FOR e2 in NEIGHBORS(vertices, edges, e1.edge._to, "inbound", [ { "$label": "likes" } ] )
RETURN 1
)
RETURN length(lst)
Run Code Online (Sandbox Code Playgroud)
这给了我一个相同数量级的延迟.
如果我尝试在Titan或Neo4j数据库上运行相同的查询(使用相同的数据),查询几乎立即返回(感知时间:<200ms)
所以在我看来,ArangoDB图形功能是"传统文档数据库"之上的"智能图层",但ArangoDB不是"本机"图形数据库.
为了证实这种感觉,我转换数据以在PostgreSQL中加载它并运行一个查询(你可以假设有一个多表JOIN)并得到类似的(对ArangoDB)执行延迟
我做错了什么(在AQL查询中)?
有没有办法优化数据库以获得更好的遍历时间?
在PostgreSQL中,从概念上讲,我会混合使用edge和node并使用CLUSTER子句对数据进行物理排序,在ArangoDB中可以做类似的事情吗?(我认为它会很难,因为它会涉及"交错"边缘和节点,只是一种直觉)
在ArangoDB的上下文中,有不同的数据库shell来查询数据:
arangosh:基于JavaScript的控制台
AQL:Arangodb查询语言,看到http://www.arangodb.org/2012/06/20/querying-a-nosql-database-the-elegant-way
MRuby:嵌入式Ruby
虽然我理解使用JavaScript和MRuby,但我不确定为什么我会学习,以及我将使用AQL的地方.有没有关于此的信息?是否将AQL直接POST到数据库服务器?
假设我们有一个食品项目数据库,例如:
item1 = {name: 'item1', tags: ['mexican', 'spicy']};
item2 = {name: 'item2', tags: ['sweet', 'chocolate', 'nuts']};
item3 = {name: 'item3', tags: ['sweet', 'vanilla', 'cold']};
Run Code Online (Sandbox Code Playgroud)
我们有一个用户正在寻找食物推荐,他们在那里指出他们对某些标签的偏好权重:
foodPref = {sweet: 4, chocolate: 11}
Run Code Online (Sandbox Code Playgroud)
现在我们需要计算每个项目得分的好坏并推荐最佳项目:
item1 score = 0 (doesn't contain any of the tags user is looking for)
item2 score = 4 (contains the tag 'sweet')
item3 score = 15 (contains the tag 'sweet' and 'chocolate')
Run Code Online (Sandbox Code Playgroud)
获取建议的正确方法是什么 - 自定义遍历对象或仅使用AQL过滤和计数或仅在Foxx(javascript层)中实现它?
另外,您可以帮助您建议使用方法的示例实现吗?
提前致谢!
我正在使用SUM()聚合函数在arangodb中尝试一个相当基本的任务.
这是一个工作查询,它返回正确的数据(虽然尚未汇总):
FOR m IN pkg_spp_RegMem
FILTER m.memberId == "40289"
COLLECT member = m.memberId INTO g
RETURN { "memberId" : member, "amount" : g[*].m[*].items }
Run Code Online (Sandbox Code Playgroud)
这将返回以下结果:
[
{
"memberId": "40289",
"amount": [
[
{
"amount": 50,
"description": "some description"
}
],
[
{
"amount": 50,
"description": "some description"
},
{
"amount": 500,
"description": "some description"
},
{
"amount": 0,
"description": "some description"
}
],
[
{
"amount": 0,
"description": "some description"
},
]
]
}
]
Run Code Online (Sandbox Code Playgroud)
我使用Collect对结果进行分组,因为给定的memberId可能有多个'RegMem'对象.从查询/结果中可以看出,每个对象都有一个名为"items"的较小对象列表,每个项目都有一个数量和一个描述.
我希望SUM()按成员金额.但是,像这样调整查询不起作用:
FOR m …Run Code Online (Sandbox Code Playgroud) 我在使用Java查询ArangoDB中的Arays值时遇到问题.我尝试过使用String []和ArrayList,两者都没有成功.
我的查询:
FOR document IN documents FILTER @categoriesArray IN document.categories[*].title RETURN document
Run Code Online (Sandbox Code Playgroud)
BindParams:
Map<String, Object> bindVars = new MapBuilder().put("categoriesArray", categoriesArray).get();
Run Code Online (Sandbox Code Playgroud)
categoriesArray包含一堆字符串.我不确定为什么它没有返回任何结果,因为如果我查询使用:
FOR document IN documents FILTER "Politics" IN document.categories[*].title RETURN document
Run Code Online (Sandbox Code Playgroud)
我得到了我正在寻找的结果.只是在使用Array或ArrayList时没有.
我也试过查询:
FOR document IN documents FILTER ["Politics","Law] IN document.categories[*].title RETURN document
Run Code Online (Sandbox Code Playgroud)
为了模拟ArrayList,但这不会返回任何结果.我会查询使用一堆单独的字符串,但是有太多的东西,当我用一个很长的字符串查询时,我从Java驱动程序中得到一个错误.因此,我必须使用Array或ArrayList进行查询.
categoriesArray的一个例子:
["Politics", "Law", "Nature"]
Run Code Online (Sandbox Code Playgroud)
数据库的示例图像:

在我的ArangoDB图中,我有一个主题,与该主题相关联的消息线程,以及这些消息线程内的消息.我想以这样一种方式遍历图形,即返回与消息线程关联的数据以及消息线程内的消息计数.
数据的结构非常简单:我有主题节点,边缘扩展到线程节点,日期和类别相关联,以及从线程节点到消息节点的边缘.
我想返回存储在线程节点中的数据和附加到线程的消息计数.
我不确定如何使用for v, e, p in 1..2 outbound语法执行此操作.我应该for v, e, p in outbound在里面使用嵌套图吗?这仍然是高性能的吗?
我的部分图表是使用两个大型集合之间的巨型连接构建的,每次我将文档添加到任一集合时都会运行它.该查询基于较旧的帖子.
FOR fromItem IN fromCollection
FOR toItem IN toCollection
FILTER fromItem.fromAttributeValue == toItem.toAttributeValue
INSERT { _from: fromItem._id, _to: toItem._id, otherAttributes: {}} INTO edgeCollection
Run Code Online (Sandbox Code Playgroud)
这需要大约55,000秒才能完成我的数据集.我绝对欢迎提出更快的建议.
但我有两个相关的问题:
upsert没关系,但在这种情况下,因为我无法预先知道密钥,所以对我没有帮助.为了获得前面的密钥,我需要通过示例查询以找到其他相同的现有边的密钥.这似乎是合理的,只要它不会破坏我的性能,但我不知道如何在AQL中有条件地构造我的查询,以便在等效边缘尚不存在的情况下插入边缘,但如果等效边缘则不执行任何操作确实存在.我怎样才能做到这一点?我试图使用AQL来更新整个节点集合,名为Nodes,取决于它们具有的边缘类型.
需求:
我的概念方法:
我尝试了什么
FOR v,e,p
In 1..10
ANY v
EntityRelationTest
OPTIONS {uniqueVertices:"global",bfs:true}
FILTER p.edges[*].relationType[0]== "EQUALS"
UPDATE v WITH { typeName2:"test1"} IN EntityTest
return NEW
Run Code Online (Sandbox Code Playgroud)
但我对arangodb AQL很新,有可能是上面的东西吗?
我是arangoDB的新手,有图表.我只是想知道构建边缘是否更快或使用'DOCUMENT()'来进行非常简单的1:1连接,而不需要查询图形?
LET a = DOCUMENT(@from)
FOR v IN OUTBOUND a
CollectionAHasCollectionB
RETURN MERGE(a,{b:v})
Run Code Online (Sandbox Code Playgroud)
VS
LET a = DOCUMENT(@from)
RETURN MERGE(a,{b:DOCUMENT(a.bId)}
Run Code Online (Sandbox Code Playgroud)