MongoDB(42)如何使用$project阶段?

在MongoDB中,使用 $project 阶段可以重塑每个文档的结构,类似于SQL中的 SELECT 子句。你可以使用 $project 来包括或排除字段、创建新的字段、重命名字段,甚至执行一些简单的运算。

使用 $project 阶段的基本结构

javascript 复制代码
{
  $project: {
    <field1>: <expression1>,
    <field2>: <expression2>,
    // 其他字段
  }
}
  • <field> 是你想要包含在输出文档中的字段名称。
  • <expression> 是一个包括或排除字段的布尔值、算术操作、字符串操作、日期操作等。

代码示例

以下是使用Node.js进行投影操作的详细示例。首先确保安装了MongoDB的Node.js驱动:

bash 复制代码
npm install mongodb
插入示例数据
javascript 复制代码
const { MongoClient } = require('mongodb');

async function insertData() {
    const uri = "mongodb://localhost:27017";
    const client = new MongoClient(uri, { useUnifiedTopology: true });

    try {
        await client.connect();
        const db = client.db('myDatabase');
        const collection = db.collection('orders');

        await collection.deleteMany({}); // 清空集合

        await collection.insertMany([
            { customerId: 1, amount: 100, status: "shipped", date: new Date("2021-01-01") },
            { customerId: 1, amount: 200, status: "pending", date: new Date("2021-02-01") },
            { customerId: 2, amount: 150, status: "shipped", date: new Date("2021-03-01") },
            { customerId: 2, amount: 50, status: "pending", date: new Date("2021-04-01") },
            { customerId: 3, amount: 250, status: "shipped", date: new Date("2021-05-01") }
        ]);

        console.log("Data inserted");
    } finally {
        await client.close();
    }
}

insertData().catch(console.error);
使用 $project 进行投影
javascript 复制代码
async function aggregateData() {
    const uri = "mongodb://localhost:27017";
    const client = new MongoClient(uri, { useUnifiedTopology: true });

    try {
        await client.connect();
        const db = client.db('myDatabase');
        const collection = db.collection('orders');

        // 使用 $project 选择特定字段
        console.log("\n$project stage (select specific fields):");
        let result = await collection.aggregate([
            {
              $project: {
                _id: 0,  // 不包括 _id 字段
                customerId: 1,  // 包括 customerId 字段
                amount: 1,  // 包括 amount 字段
                status: 1  // 包括 status 字段
              }
            }
        ]).toArray();
        console.log(result);

        // 使用 $project 创建新的字段
        console.log("\n$project stage (create new fields):");
        result = await collection.aggregate([
            {
              $project: {
                customerId: 1,
                amount: 1,
                status: 1,
                amountWithTax: { $multiply: ["$amount", 1.1] }  // 创建新的字段 amountWithTax,值为 amount 的 1.1 倍
              }
            }
        ]).toArray();
        console.log(result);

        // 使用 $project 重命名字段
        console.log("\n$project stage (rename fields):");
        result = await collection.aggregate([
            {
              $project: {
                _id: 0,
                customer: "$customerId",  // 将 customerId 字段重命名为 customer
                total: "$amount",  // 将 amount 字段重命名为 total
                status: 1,
                date: 1
              }
            }
        ]).toArray();
        console.log(result);

        // 使用 $project 包含计算字段
        console.log("\n$project stage (include calculated fields):");
        result = await collection.aggregate([
            {
              $project: {
                customerId: 1,
                amount: 1,
                status: 1,
                year: { $year: "$date" },  // 包括 year 字段,值为 date 字段的年份
                month: { $month: "$date" }  // 包括 month 字段,值为 date 字段的月份
              }
            }
        ]).toArray();
        console.log(result);

    } finally {
        await client.close();
    }
}

aggregateData().catch(console.error);

在这个示例中,我们演示了如何使用 $project 阶段进行投影操作:

  1. 选择特定字段
  2. 创建新的字段
  3. 重命名字段
  4. 包含计算字段

运行这个脚本后,你会得到如下结果(示例输出):

javascript 复制代码
// select specific fields 结果
$project stage (select specific fields):
[
  { customerId: 1, amount: 100, status: 'shipped' },
  { customerId: 1, amount: 200, status: 'pending' },
  { customerId: 2, amount: 150, status: 'shipped' },
  { customerId: 2, amount: 50, status: 'pending' },
  { customerId: 3, amount: 250, status: 'shipped' }
]

// create new fields 结果
$project stage (create new fields):
[
  { customerId: 1, amount: 100, status: 'shipped', amountWithTax: 110 },
  { customerId: 1, amount: 200, status: 'pending', amountWithTax: 220 },
  { customerId: 2, amount: 150, status: 'shipped', amountWithTax: 165 },
  { customerId: 2, amount: 50, status: 'pending', amountWithTax: 55 },
  { customerId: 3, amount: 250, status: 'shipped', amountWithTax: 275 }
]

// rename fields 结果
$project stage (rename fields):
[
  { customer: 1, total: 100, status: 'shipped', date: 2021-01-01T00:00:00.000Z },
  { customer: 1, total: 200, status: 'pending', date: 2021-02-01T00:00:00.000Z },
  { customer: 2, total: 150, status: 'shipped', date: 2021-03-01T00:00:00.000Z },
  { customer: 2, total: 50, status: 'pending', date: 2021-04-01T00:00:00.000Z },
  { customer: 3, total: 250, status: 'shipped', date: 2021-05-01T00:00:00.000Z }
]

// include calculated fields 结果
$project stage (include calculated fields):
[
  { customerId: 1, amount: 100, status: 'shipped', year: 2021, month: 1 },
  { customerId: 1, amount: 200, status: 'pending', year: 2021, month: 2 },
  { customerId: 2, amount: 150, status: 'shipped', year: 2021, month: 3 },
  { customerId: 2, amount: 50, status: 'pending', year: 2021, month: 4 },
  { customerId: 3, amount: 250, status: 'shipped', year: 2021, month: 5 }
]

其他语言示例

类似的投影操作也可以在其他编程语言中实现,如Python。以下是Python的示例代码:

安装PyMongo

在终端中运行以下命令来安装PyMongo:

bash 复制代码
pip install pymongo
使用Python进行投影
python 复制代码
from pymongo import MongoClient

def main():
    client = MongoClient('mongodb://localhost:27017/')
    db = client['myDatabase']
    collection = db['orders']

    # 使用 $project 选择特定字段
    print("\n$project stage (select specific fields):")
    pipeline = [
        {
          '$project': {
            '_id': 0,  # 不包括 _id 字段
            'customerId': 1,  # 包括 customerId 字段
            'amount': 1,  # 包括 amount 字段
            'status': 1  # 包括 status 字段
          }
        }
    ]
    result = list(collection.aggregate(pipeline))
    for doc in result:
        print(doc)

    # 使用 $project 创建新的字段
    print("\n$project stage (create new fields):")
    pipeline = [
        {
          '$project': {
            'customerId': 1,
            'amount': 1,
            'status': 1,
            'amountWithTax': { '$multiply': ["$amount", 1.1] }  # 创建新的字段 amountWith
相关推荐
AAA代码批发商14 分钟前
Days 39 Linux C 开发之 SQLite 数据库完整学习笔记
linux·c语言·数据库
笑梦无境14 分钟前
mysql的安装及配置(3)
数据库·mysql·adb
电商API_1800790524714 分钟前
跨境1688代采商家,如何借助API打通供应链,实现效率跃迁
大数据·数据库·网络爬虫
小雪崩16 分钟前
嵌入式学习 day40:数据库
数据库·学习
Aloudata34 分钟前
语义层 vs MCP 工具层:Agent 调用数据时,语义应该放在哪一层
数据库·数据分析·chatbi·data agent·语义层
zcmodeltech34 分钟前
源网荷储一体化沙盘模型多场景控制系统设计——基于STM32与Modbus RTU的源网荷储、多能互补、冷热电三联供全场景联动方案,服务范围覆盖全国
数据库·人工智能·stm32·单片机·嵌入式硬件
数智启示录37 分钟前
PostgreSQL 执行计划实战(第 9 篇):SQL 和索引没变,计划为什么突然慢一百倍
数据库·经验分享·sql·postgresql·面试
Gent_倪1 小时前
MySQL分库、分表、分区详解
数据库·mysql
额额额对了1 小时前
Linux 数据库开发实战:使用 C 语言与 SQLite3 构建轻量级终端词典
linux·数据库·oracle
qq_246839751 小时前
postgresql xxhash64 哈希函数实现
数据库·postgresql·哈希算法