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
相关推荐
Victor3562 小时前
MongoDB(43)什么是嵌入式文档?
后端
Darkdreams2 小时前
SpringBoot项目集成ONLYOFFICE
java·spring boot·后端
bropro3 小时前
【Spring Boot】Spring AOP中的环绕通知
spring boot·后端·spring
lhbian3 小时前
【Spring Cloud Alibaba】基于Spring Boot 3.x 搭建教程
java·spring boot·后端
IT_陈寒3 小时前
Redis性能提升3倍的5个冷门技巧,90%开发者都不知道!
前端·人工智能·后端
LucianaiB3 小时前
OpenClaw 安装后必看!你真的会科学养虾吗?第1天和第47天的Openclaw有什么区别?
后端
寻见9034 小时前
智能体开发_07Function Calling道法术器拆解,一文搞懂大模型如何“做事”
人工智能·后端·ai编程
奋斗小强4 小时前
数据库优化:从慢查询到索引,让系统快 10 倍
后端
重庆穿山甲4 小时前
从零到精通:OpenClaw完整生命周期指南
前端·后端·架构