4

我想找到一组没有个人资料的用户。

ArangoDB 2.4.3

LENGTH(users) -> 130k
LENGTH(profiles) -> 110k

users.userId -> unique hash index
profiles.userId -> unique hash index

我制作的这个 AQL 片段比仲夏穿越大峡谷的蜗牛还慢。

LET usersWithProfiles = ( /* This part is ok */
FOR i IN users
    FOR j IN profiles
        FILTER i.userId == j.userId
RETURN i
)

LET usersWithoutProfiles = ( /* This is not */
FOR i IN usersWithProfiles
    FILTER i NOT IN users
RETURN i
)

RETURN LENGTH(usersWithoutProfiles)

我很确定有一种完全理智的方法可以正确地做到这一点,但我错过了它。有任何想法吗?

编辑1(在@ dothebart的回复之后):

这是新查询,但仍然很慢

LET userIds_usersWithProfile = (
FOR i IN users
    FOR j IN profile
        FILTER i.userId == j.userId
RETURN i.userId
)

LET usersWithoutProfiles = (
FOR i IN users 
    FILTER i.userId NOT IN userIds_usersWithProfile
RETURN i
)

RETURN LENGTH(usersWithoutProfiles)
4

2 回答 2

7

另请注意,原始查询的这一部分非常昂贵:

LET usersWithoutProfiles = (
  FOR i IN usersWithProfiles
    FILTER i NOT IN users
    RETURN i
)

原因是FILTERusing users,此时它是一个表达式,它将集合中的所有文档构建为一个数组。我建议使用此查询,而不是使用此查询,它将返回_key没有关联个人资料记录的用户的属性:

FOR user IN users 
  LET profile = (
    FOR profile IN profiles 
      FILTER profile.userId == user.userId 
      RETURN 1
  ) 
  FILTER LENGTH(profile) == 0 
  RETURN user._key
于 2015-02-10T18:26:17.973 回答
4

性能不佳的原因是它无法为您的操作使用索引,因为它需要对集合中的每个文档进行全面比较。

您可以使用解释https://www.arangodb.com/2015/02/02/arangodb-2-4-2实用程序让 arangodb 告诉您查询的费用在哪里。

您的查询可能不会达到您的预期。usersWithoutProfiles 将为空,因为任何具有 Profile 的用户都可以在 users 集合中找到。如果您想拥有用户集合的另一部分,它可能如下所示:

LET usersWithProfiles = ( /* This part is ok */
FOR i IN users
    FOR j IN profiles
        FILTER i.userId == j.userId
RETURN i
)

/* now we pick the IDs, we could have done that in your first query... */
LET userWithProfilesIds = FOR i IN userWithProfiles RETURN i.userId;

/* now filter the user list by that */
LET usersWithoutProfiles = FOR i IN users 
     FILTER i.userId NOT IN userWithProfileIds
     RETURN i;

RETURN LENGTH(usersWithoutProfiles)

应该给你一个正确的结果。

于 2015-02-10T17:55:20.310 回答