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
相关推荐
南墙上的石头11 小时前
麒麟 V10 重装人大金仓 V8R6 踩坑实录(含 MySQL 兼容模式)
数据库·mysql
画中有画12 小时前
论向量数据库在项目中的应用
数据库
spider_xcxc12 小时前
Redis 数据库高质量实践指南(一)
运维·数据库·redis·oracle·云计算
l1t13 小时前
在linux和windows中解决duckdb 1.6dev版本输出执行计划报错问题
linux·运维·数据库·windows·duckdb
执子手 吹散苍茫茫烟波13 小时前
RC 隔离级别下 MySQL InnoDB 死锁典型案例
数据库·mysql
落叶-IT14 小时前
Java异常处理深度实战教程:异常传播的失败场景分析
数据库·oracle
执子手 吹散苍茫茫烟波15 小时前
常见的数据库隔离级别以及企业里常用的是什么方案
数据库
Database_Cool_16 小时前
数据库慢查询优化首选方案:阿里云 RDS 性能洞察+自动诊断
数据库·人工智能·阿里云
YOU OU16 小时前
Redis初识
数据库·redis·缓存
长孙豪翔16 小时前
在.net中读写config文件的各种方法
java·数据库·.net