文档删除 #

一、删除概述 #

ArangoDB使用REMOVE关键字删除文档,删除操作不可恢复。

1.1 删除方式 #

方式 说明
REMOVE AQL删除语法
remove JavaScript API
truncate 清空整个集合

1.2 注意事项 #

text
警告:
├── 删除操作不可恢复
├── 边文档删除不影响顶点
├── 删除会生成新的_rev
└── 建议使用事务保证一致性

二、单条删除 #

2.1 使用_key删除 #

aql
REMOVE "user_001" IN users

2.2 使用_id删除 #

aql
REMOVE "users/user_001" IN users

2.3 使用文档对象删除 #

aql
REMOVE { _key: "user_001" } IN users

2.4 返回被删除的文档 #

aql
REMOVE "user_001" IN users
RETURN OLD

2.5 JavaScript删除 #

javascript
db.users.remove("user_001");

2.6 返回删除结果 #

javascript
var result = db.users.remove("user_001");
print(result);

三、条件删除 #

3.1 按条件删除 #

aql
FOR user IN users
    FILTER user.status == "inactive"
    REMOVE user IN users

3.2 返回删除的文档 #

aql
FOR user IN users
    FILTER user.status == "inactive"
    REMOVE user IN users
    RETURN OLD

3.3 多条件删除 #

aql
FOR user IN users
    FILTER user.status == "deleted"
    AND user.deletedAt < DATE_SUBTRACT(DATE_NOW(), 30, "days")
    REMOVE user IN users

3.4 范围删除 #

aql
FOR user IN users
    FILTER user.age < 18
    REMOVE user IN users

3.5 使用子查询删除 #

aql
LET inactiveUsers = (
    FOR user IN users
        FILTER user.lastLogin < DATE_SUBTRACT(DATE_NOW(), 90, "days")
        RETURN user._key
)
FOR key IN inactiveUsers
    REMOVE key IN users

四、批量删除 #

4.1 删除多个文档 #

aql
FOR key IN ["user_001", "user_002", "user_003"]
    REMOVE key IN users

4.2 批量删除并返回 #

aql
FOR user IN users
    FILTER user.status == "expired"
    REMOVE user IN users
    RETURN OLD._key

4.3 分批删除 #

aql
FOR user IN users
    FILTER user.status == "inactive"
    LIMIT 1000
    REMOVE user IN users

4.4 JavaScript批量删除 #

javascript
var keys = ["user_001", "user_002", "user_003"];
keys.forEach(function(key) {
    db.users.remove(key);
});

4.5 使用removeByExample #

javascript
db.users.removeByExample({ status: "inactive" });

五、删除选项 #

5.1 waitForSync #

aql
REMOVE "user_001" IN users
OPTIONS { waitForSync: true }

5.2 ignoreRevs #

忽略版本检查:

aql
REMOVE {
    _key: "user_001",
    _rev: "_old_rev"
} IN users
OPTIONS { ignoreRevs: true }

5.3 returnOld #

返回被删除的文档:

aql
REMOVE "user_001" IN users
OPTIONS { returnOld: true }
RETURN OLD

5.4 完整选项示例 #

aql
REMOVE "user_001" IN users
OPTIONS {
    waitForSync: true,
    ignoreRevs: true
}
RETURN OLD

六、清空集合 #

6.1 truncate #

javascript
db.users.truncate();

6.2 AQL方式 #

aql
FOR user IN users
    REMOVE user IN users

6.3 区别 #

方式 速度 重置计数器
truncate
AQL循环

七、删除边文档 #

7.1 删除单条边 #

aql
REMOVE "follow_001" IN follows

7.2 删除用户的所有边 #

aql
FOR edge IN follows
    FILTER edge._from == "users/user_001" OR edge._to == "users/user_001"
    REMOVE edge IN follows

7.3 删除特定类型的边 #

aql
FOR edge IN follows
    FILTER edge.type == "temporary"
    REMOVE edge IN follows

八、级联删除 #

8.1 删除用户及相关数据 #

aql
LET userId = "user_001"
LET userEdges = (
    FOR edge IN follows
        FILTER edge._from == CONCAT("users/", userId) 
            OR edge._to == CONCAT("users/", userId)
        RETURN edge._key
)
FOR key IN userEdges
    REMOVE key IN follows
REMOVE userId IN users

8.2 使用事务级联删除 #

javascript
db._executeTransaction({
    collections: { write: ["users", "posts", "comments"] },
    action: function() {
        var db = require("@arangodb").db;
        var userId = "user_001";
        
        db._query(`
            FOR comment IN comments
                FILTER comment.userId == @userId
                REMOVE comment IN comments
        `, { userId: userId });
        
        db._query(`
            FOR post IN posts
                FILTER post.authorId == @userId
                REMOVE post IN posts
        `, { userId: userId });
        
        db.users.remove(userId);
    }
});

8.3 删除顶点及所有边 #

aql
LET vertexId = "users/user_001"
FOR v, e IN ANY vertexId GRAPH "social"
    REMOVE e IN follows
REMOVE vertexId IN users

九、软删除 #

9.1 实现软删除 #

aql
UPDATE "user_001" WITH {
    deleted: true,
    deletedAt: DATE_NOW()
} IN users

9.2 查询时过滤 #

aql
FOR user IN users
    FILTER user.deleted != true
    RETURN user

9.3 恢复软删除 #

aql
UPDATE "user_001" WITH {
    deleted: false,
    deletedAt: null
} IN users

9.4 永久删除软删除数据 #

aql
FOR user IN users
    FILTER user.deleted == true
    AND user.deletedAt < DATE_SUBTRACT(DATE_NOW(), 30, "days")
    REMOVE user IN users

十、JavaScript API #

10.1 remove #

javascript
db.users.remove("user_001");

10.2 removeByExample #

javascript
db.users.removeByExample({ status: "inactive" });

10.3 removeByKeys #

javascript
db.users.removeByKeys(["user_001", "user_002", "user_003"]);

10.4 truncate #

javascript
db.users.truncate();

10.5 删除并检查 #

javascript
if (db.users.exists("user_001")) {
    db.users.remove("user_001");
    print("删除成功");
} else {
    print("文档不存在");
}

十一、实战示例 #

11.1 删除过期会话 #

aql
FOR session IN sessions
    FILTER session.expiresAt < DATE_NOW()
    REMOVE session IN sessions

11.2 清理测试数据 #

aql
FOR user IN users
    FILTER user.email LIKE "%@test.com"
    REMOVE user IN users

11.3 删除重复文档 #

aql
FOR user IN users
    COLLECT email = user.email WITH COUNT INTO count
    FILTER count > 1
    LET duplicates = (
        FOR u IN users
            FILTER u.email == email
            SORT u.createdAt ASC
            LIMIT 1, count - 1
            RETURN u._key
    )
    FOR key IN duplicates
        REMOVE key IN users

11.4 删除孤立边 #

aql
FOR edge IN follows
    LET fromExists = DOCUMENT(edge._from)
    LET toExists = DOCUMENT(edge._to)
    FILTER fromExists == null OR toExists == null
    REMOVE edge IN follows

11.5 批量删除大量数据 #

javascript
function batchRemove(collection, batchSize) {
    var removed = 0;
    while (true) {
        var result = db._query(`
            FOR doc IN @@collection
                LIMIT @batchSize
                REMOVE doc IN @@collection
                RETURN 1
        `, { 
            "@collection": collection, 
            batchSize: batchSize 
        });
        var count = result.toArray().length;
        removed += count;
        if (count < batchSize) break;
    }
    return removed;
}

var total = batchRemove("logs", 1000);
print("共删除 " + total + " 条记录");

十二、性能优化 #

12.1 使用索引 #

确保删除条件字段有索引:

javascript
db.users.ensureHashIndex(["status"]);

12.2 分批删除 #

aql
FOR user IN users
    FILTER user.status == "inactive"
    LIMIT 1000
    REMOVE user IN users

12.3 使用truncate #

清空整个集合时使用truncate:

javascript
db.users.truncate();

十三、错误处理 #

13.1 文档不存在 #

aql
REMOVE "nonexistent_key" IN users
OPTIONS { ignoreErrors: true }

13.2 JavaScript错误处理 #

javascript
try {
    db.users.remove("user_001");
} catch (e) {
    if (e.errorNum === 1202) {
        print("文档不存在");
    } else if (e.errorNum === 1200) {
        print("版本冲突");
    }
}

13.3 事务回滚 #

javascript
try {
    db._executeTransaction({
        collections: { write: ["users", "orders"] },
        action: function() {
            var db = require("@arangodb").db;
            db.users.remove("user_001");
            throw new Error("模拟错误");
        }
    });
} catch (e) {
    print("事务已回滚: " + e.message);
}

十四、总结 #

文档删除要点:

  1. REMOVE:AQL删除语法
  2. 条件删除:结合FILTER使用
  3. 批量删除:使用FOR循环
  4. 级联删除:使用事务保证一致性
  5. 软删除:标记删除而非真正删除

下一步,让我们学习基础查询!

最后更新:2026-03-27