文档插入 #

一、插入概述 #

文档是ArangoDB中数据存储的基本单位,以JSON格式存储在集合中。

1.1 文档结构 #

json
{
    "_key": "user_001",
    "_id": "users/user_001",
    "_rev": "_abc123",
    "name": "张三",
    "email": "zhangsan@example.com",
    "age": 28
}

1.2 系统属性 #

属性 说明 自动生成
_key 文档唯一标识 是(可手动指定)
_id 全局标识(集合名/_key)
_rev 版本号

二、单条插入 #

2.1 AQL插入 #

aql
INSERT {
    name: "张三",
    email: "zhangsan@example.com",
    age: 28
} INTO users

2.2 指定_key #

aql
INSERT {
    _key: "user_001",
    name: "张三",
    email: "zhangsan@example.com",
    age: 28
} INTO users

2.3 JavaScript插入 #

javascript
db.users.insert({
    name: "张三",
    email: "zhangsan@example.com",
    age: 28
});

2.4 返回插入的文档 #

aql
INSERT {
    name: "张三",
    email: "zhangsan@example.com"
} INTO users
RETURN NEW

输出:

json
{
    "_key": "12345",
    "_id": "users/12345",
    "_rev": "_abc123",
    "name": "张三",
    "email": "zhangsan@example.com"
}

2.5 返回特定字段 #

aql
INSERT {
    name: "张三",
    email: "zhangsan@example.com"
} INTO users
RETURN NEW._id

三、批量插入 #

3.1 使用FOR循环 #

aql
FOR user IN [
    { name: "张三", email: "zhangsan@example.com" },
    { name: "李四", email: "lisi@example.com" },
    { name: "王五", email: "wangwu@example.com" }
]
INSERT user INTO users

3.2 返回所有插入的文档 #

aql
FOR user IN [
    { name: "张三", email: "zhangsan@example.com" },
    { name: "李四", email: "lisi@example.com" }
]
INSERT user INTO users
RETURN NEW

3.3 JavaScript批量插入 #

javascript
db.users.insert([
    { name: "张三", email: "zhangsan@example.com" },
    { name: "李四", email: "lisi@example.com" },
    { name: "王五", email: "wangwu@example.com" }
]);

3.4 从另一个集合复制 #

aql
FOR doc IN source_collection
    INSERT doc INTO target_collection

3.5 批量插入并转换 #

aql
FOR i IN 1..100
    INSERT {
        _key: CONCAT("user_", i),
        name: CONCAT("用户", i),
        score: RAND() * 100
    } INTO users

四、UPSERT操作 #

4.1 基本UPSERT #

如果存在则更新,不存在则插入:

aql
UPSERT { email: "zhangsan@example.com" }
INSERT { 
    name: "张三", 
    email: "zhangsan@example.com",
    createdAt: DATE_NOW()
}
UPDATE {
    name: "张三",
    updatedAt: DATE_NOW()
} IN users

4.2 返回操作结果 #

aql
UPSERT { email: "zhangsan@example.com" }
INSERT { name: "张三", email: "zhangsan@example.com" }
UPDATE { name: "张三" } IN users
RETURN { doc: NEW, type: OLD ? "update" : "insert" }

4.3 UPSERT选项 #

aql
UPSERT { email: "zhangsan@example.com" }
INSERT { name: "张三", email: "zhangsan@example.com" }
UPDATE { name: "张三" } IN users
OPTIONS { ignoreErrors: true }

五、插入选项 #

5.1 waitForSync #

等待数据写入磁盘:

aql
INSERT {
    name: "张三",
    email: "zhangsan@example.com"
} INTO users
OPTIONS { waitForSync: true }

5.2 overwrite #

覆盖已存在的文档:

aql
INSERT {
    _key: "user_001",
    name: "张三",
    email: "zhangsan@example.com"
} INTO users
OPTIONS { overwrite: true }

5.3 overwriteMode #

覆盖模式:

aql
INSERT {
    _key: "user_001",
    name: "张三"
} INTO users
OPTIONS { overwriteMode: "replace" }
模式 说明
replace 完全替换
update 合并更新
ignore 忽略已存在的

5.4 returnNew #

返回新文档:

aql
INSERT {
    name: "张三"
} INTO users
OPTIONS { returnNew: true }
RETURN NEW

六、插入边文档 #

6.1 创建边文档 #

aql
INSERT {
    _from: "users/user_001",
    _to: "users/user_002",
    type: "follows",
    createdAt: DATE_NOW()
} INTO follows

6.2 批量创建边 #

aql
FOR i IN 1..10
    INSERT {
        _from: CONCAT("users/user_", i),
        _to: CONCAT("users/user_", i + 1),
        createdAt: DATE_NOW()
    } INTO follows

6.3 基于查询创建边 #

aql
FOR user IN users
    FILTER user.city == "北京"
    FOR other IN users
        FILTER other.city == "北京" AND other._key != user._key
        INSERT {
            _from: user._id,
            _to: other._id,
            type: "same_city"
        } INTO relations

七、使用变量插入 #

7.1 使用LET定义变量 #

aql
LET name = "张三"
LET email = "zhangsan@example.com"
INSERT {
    name: name,
    email: email
} INTO users

7.2 使用绑定参数 #

aql
INSERT @doc INTO users

JavaScript调用:

javascript
db._query(
    "INSERT @doc INTO users RETURN NEW",
    { doc: { name: "张三", email: "zhangsan@example.com" } }
);

7.3 批量参数插入 #

aql
FOR doc IN @docs
    INSERT doc INTO users

JavaScript调用:

javascript
db._query(
    "FOR doc IN @docs INSERT doc INTO users RETURN NEW",
    { 
        docs: [
            { name: "张三", email: "zhangsan@example.com" },
            { name: "李四", email: "lisi@example.com" }
        ]
    }
);

八、插入验证 #

8.1 使用Schema验证 #

创建带Schema的集合:

javascript
db._create("users", {
    schema: {
        rule: {
            type: "object",
            properties: {
                name: { type: "string" },
                email: { type: "string", format: "email" },
                age: { type: "number", minimum: 0 }
            },
            required: ["name", "email"]
        }
    }
});

插入有效文档:

aql
INSERT {
    name: "张三",
    email: "zhangsan@example.com",
    age: 28
} INTO users

插入无效文档会报错:

aql
INSERT {
    name: "张三",
    email: "invalid-email",
    age: -1
} INTO users

8.2 唯一索引验证 #

创建唯一索引:

javascript
db.users.ensureHashIndex(["email"], { unique: true });

重复插入会报错:

aql
INSERT { name: "张三", email: "zhangsan@example.com" } INTO users
INSERT { name: "李四", email: "zhangsan@example.com" } INTO users

九、实战示例 #

9.1 创建用户并设置默认值 #

aql
INSERT {
    name: "张三",
    email: "zhangsan@example.com",
    status: "active",
    role: "user",
    createdAt: DATE_NOW(),
    updatedAt: DATE_NOW(),
    loginCount: 0
} INTO users
RETURN NEW

9.2 从CSV导入 #

aql
LET lines = @csvLines
FOR line IN lines
    LET parts = SPLIT(line, ",")
    INSERT {
        name: parts[0],
        email: parts[1],
        age: TO_NUMBER(parts[2])
    } INTO users

9.3 创建嵌套文档 #

aql
INSERT {
    name: "张三",
    contact: {
        email: "zhangsan@example.com",
        phone: "13800138000"
    },
    address: {
        city: "北京",
        district: "朝阳区",
        street: "朝阳路100号"
    },
    preferences: {
        theme: "dark",
        language: "zh-CN"
    }
} INTO users

9.4 创建带数组字段的文档 #

aql
INSERT {
    name: "张三",
    hobbies: ["阅读", "游泳", "编程"],
    tags: ["developer", "backend"],
    scores: [90, 85, 92, 88]
} INTO users

十、性能优化 #

10.1 批量插入优化 #

aql
FOR i IN 1..10000
    INSERT {
        name: CONCAT("用户", i),
        value: RAND()
    } INTO large_collection
OPTIONS { batchSize: 1000 }

10.2 禁用索引后插入 #

javascript
db.large_collection.dropIndex("hash_index_name");
db._query("FOR i IN 1..10000 INSERT { name: CONCAT('用户', i) } INTO large_collection");
db.large_collection.ensureHashIndex(["name"]);

10.3 使用事务批量插入 #

javascript
db._executeTransaction({
    collections: { write: ["users"] },
    action: function() {
        var db = require("@arangodb").db;
        for (var i = 0; i < 1000; i++) {
            db.users.insert({ name: "用户" + i });
        }
    }
});

十一、错误处理 #

11.1 忽略错误 #

aql
INSERT {
    _key: "existing_key",
    name: "张三"
} INTO users
OPTIONS { ignoreErrors: true }

11.2 捕获错误 #

javascript
try {
    db.users.insert({
        _key: "existing_key",
        name: "张三"
    });
} catch (e) {
    print("插入失败: " + e.message);
}

11.3 条件插入 #

aql
LET exists = DOCUMENT("users", "user_001")
FILTER exists == null
INSERT {
    _key: "user_001",
    name: "张三"
} INTO users

十二、总结 #

文档插入要点:

  1. INSERT:基本插入语法
  2. 批量插入:使用FOR循环提高效率
  3. UPSERT:存在则更新,不存在则插入
  4. 选项:waitForSync、overwrite等
  5. 验证:Schema验证和唯一索引

下一步,让我们学习文档更新!

最后更新:2026-03-27