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
)

その理由はFILTERusingusersにあります。この時点では、コレクションからすべてのドキュメントを配列として構築する式です。これを使用する代わりに_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 は空になります。これは、プロファイルを持つすべてのユーザーが 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 に答える