Docs 菜单

Docs 主页启动和管理 MongoDBMongoDB Atlas

如何使用物化视图运行 Atlas Search 查询

在此页面上

  • 创建 purchaseOrderscollection
  • 创建updateMonthlySales函数
  • 创建updateMonthlyPurchaseOrders函数
  • 创建定时触发器
  • 在物化视图上创建 Atlas Search 索引
  • 在物化视图上运行查询

本教程介绍如何使用以下功能的组合来创建索引并针对样本数据集中 sample_supplies.sales集合和新的sample_supplies.purchaseOrders集合运行查询:

  • 按需物化视图

  • Atlas App Services 定时触发器

按需物化视图是您使用$merge聚合管道阶段创建和更新的集合。您可以在物化视图上创建 Atlas Search 索引,然后使用$search聚合管道阶段在物化视图上运行查询。

本教程将指导您完成以下步骤:

  1. sample_supplies数据库中创建名为purchaseOrders的集合。

  2. 在 App Services 用户界面中创建名为updateMonthlySales的 App Services 函数,以使用来自 Atlas 集群上示例sample_supplies.sales集合的数据来初始化monthlyPhoneTransactions物化视图。

  3. 在 App Services 用户界面中创建名为updateMonthlyPurchaseOrders的 App Services 函数,以使用您在 Atlas 集群上创建的sample_supplies.purchaseOrders集合中的数据更新monthlyPhoneTransactions物化视图。

  4. 使用 App Services 定时触发器安排以下函数以定期更新monthlyPhoneTransactions物化视图:

    1. updateMonthlySales

    2. updateMonthlyPurchaseOrders

  5. monthlyPhoneTransactions物化视图上创建 Atlas Search 索引。

  6. monthlyPhoneTransactions物化视图运行查询。

开始之前,请确保 Atlas 集群满足先决条件中所述的要求。

要创建 Atlas Search 索引,您必须拥有 Project Data Access Admin 或更高的项目访问权限。

要创建 App Services 函数和触发器,您必须对项目具有Project Owner或更高访问权限。

1
  1. 在终端窗口中打开mongosh并连接到集群。有关连接的详细说明,请参阅通过mongosh连接。

  2. 使用sample_supplies数据库:

    use sample_supplies
2

添加purchaseOrders集合,其中包含2018 1 月以来的新手机采购订单数据。运行以下命令:

db.purchaseOrders.insertMany( [
{
saleDate: ISODate("2018-01-23T21:06:49.506Z"),
items: [
{
name: 'printer paper',
tags: [ 'office', 'stationary' ],
price: Decimal128("40.01"),
quantity: 2
},
{
name: 'notepad',
tags: [ 'office', 'writing', 'school' ],
price: Decimal128("35.29"),
quantity: 2
},
{
name: 'pens',
tags: [ 'writing', 'office', 'school', 'stationary' ],
price: Decimal128("56.12"),
quantity: 5
},
{
name: 'backpack',
tags: [ 'school', 'travel', 'kids' ],
price: Decimal128("77.71"),
quantity: 2
},
{
name: 'notepad',
tags: [ 'office', 'writing', 'school' ],
price: Decimal128("18.47"),
quantity: 2
},
{
name: 'envelopes',
tags: [ 'stationary', 'office', 'general' ],
price: Decimal128("19.95"),
quantity: 8
},
{
name: 'envelopes',
tags: [ 'stationary', 'office', 'general' ],
price: Decimal128("8.08"),
quantity: 3
},
{
name: 'binder',
tags: [ 'school', 'general', 'organization' ],
price: Decimal128("14.16"),
quantity: 3
}
],
storeLocation: 'Denver',
customer: {
gender: 'M',
age: 42,
email: 'cauho@witwuta.sv',
satisfaction: 4
},
couponUsed: true,
purchaseMethod: 'Phone'
}
])
db.purchaseOrders.insertMany( [
{
saleDate: ISODate("2018-01-25T10:01:02.918Z"),
items: [
{
name: 'envelopes',
tags: [ 'stationary', 'office', 'general' ],
price: Decimal128("8.05"),
quantity: 10
},
{
name: 'binder',
tags: [ 'school', 'general', 'organization' ],
price: Decimal128("28.31"),
quantity: 9
},
{
name: 'notepad',
tags: [ 'office', 'writing', 'school' ],
price: Decimal128("20.95"),
quantity: 3
},
{
name: 'laptop',
tags: [ 'electronics', 'school', 'office' ],
price: Decimal128("866.5"),
quantity: 4
},
{
name: 'notepad',
tags: [ 'office', 'writing', 'school' ],
price: Decimal128("33.09"),
quantity: 4
},
{
name: 'printer paper',
tags: [ 'office', 'stationary' ],
price: Decimal128("37.55"),
quantity: 1
},
{
name: 'backpack',
tags: [ 'school', 'travel', 'kids' ],
price: Decimal128("83.28"),
quantity: 2
},
{
name: 'pens',
tags: [ 'writing', 'office', 'school', 'stationary' ],
price: Decimal128("42.9"),
quantity: 4
},
{
name: 'envelopes',
tags: [ 'stationary', 'office', 'general' ],
price: Decimal128("16.68"),
quantity: 2
}
],
storeLocation: 'Seattle',
customer: { gender: 'M', age: 50, email: 'keecade@hem.uy', satisfaction: 5 },
couponUsed: false,
purchaseMethod: 'Phone'
}
])
3

查询purchaseOrders集合以确认新的采购订单条目。

db.purchaseOrders.find().sort( {saleDate: -1} )

这两个查询结果反映了截至2018的 1 月的采购订单数据。

在 App Services 用户界面中创建updateMonthlySales函数。

updateMonthlySales函数定义一个monthlyPhoneTransactions物化视图,其中包含每月累计销售信息。该函数更新通过电话进行的销售的每月销售信息。

以下示例定义了该函数:

exports = function(){
var pipeline = [
{ $match: {purchaseMethod: "Phone"} },
{ $unwind: {path: "$items"}},
{ $group: {
_id: { $dateToString:
{ format: "%Y-%m", date: "$saleDate" } },
sales_quantity: { $sum: "$items.quantity"},
sales_price: { $sum: "$items.price"}
}},
{ $set: { sales_price: { $toDouble: "$sales_price"}}},
{ $merge: { into: "monthlyPhoneTransactions", whenMatched: "replace" } }
]
var monthlyPhoneTransactions = context.services.get("mongodb-atlas").db("sample_supplies").collection("sales");
return monthlyPhoneTransactions.aggregate(pipeline);
};

该函数使用以下聚合管道阶段来更新monthlyPhoneTransactions

  • $match阶段会对数据进行筛选,以仅处理在Phone内完成的销售。

  • $group阶段按年月对销售信息进行分组。此阶段输出具有以下形式的文档:

    { "_id" : "<YYYY-mm>", "sales_quantity" : <num>, "sales_amount" : <NumberDecimal> }
  • $set阶段将sales_price字段的数据类型更改为double 。 Atlas Search $search操作符不支持Decimal128数据类型。更改sales_price字段的数据类型后,您可以使用 Atlas Search 索引查询该字段。

  • $merge阶段将输出写入monthlyPhoneTransactions集合。

    该阶段根据_id字段(未分片输出集合的默认值)检查聚合结果中的文档是否与集合中的现有文档匹配

    • 当 Atlas Search 找到匹配项(即集合中已存在具有相同年份月份的文档)时,Atlas Search 会将现有文档替换为阶段中指定的聚合结果中的文档。

    • 当 Atlas Search 未找到匹配项时,Atlas Search 会将聚合结果中的文档插入到阶段指定的集合中。这是当字段没有匹配项时的默认行为。

1

要从用户界面定义新的服务器端函数,必须首先创建一个 App Services App:

  1. 如果尚未执行此操作,请单击 App Services标签页。

  2. 创建应用程序:

    • 如果您在项目中创建第一个 App Services App,则系统会显示一个不使用模板启动的选项 ( Build your own App )。选择Build your own App选项。

    • 如果您已在项目中创建至少一个 App Services App,请单击Create a New App

  3. Name字段中,输入Sales-App作为函数名称。

  4. Link your Database字段下,选择Use an existing MongoDB Atlas Data Source选项。

  5. 从下拉列表中,选择您在先决条件中创建的 Atlas 集群。

  6. 单击 Create App Service(连接)。

2

要从用户界面定义新的服务器端函数,请执行以下操作:

  1. 单击左侧导航菜单中的 Functions(函数)。

  2. 单击 Create New Function(连接)。

  3. 输入updateMonthlySales作为函数名称。

  4. Authentication 下,选择 System

3
  1. 单击 Function Editor 标签页。

  2. 将 JavaScript 代码添加到exports函数中。至少,代码必须将一个函数分配给全局变量exports

    exports = function(){
    var pipeline = [
    { $match: {purchaseMethod: "Phone"} },
    { $unwind: {path: "$items"}},
    { $group: {
    _id: { $dateToString:{ format: "%Y-%m", date: "$saleDate" } },
    sales_quantity: { $sum: "$items.quantity"},
    sales_price: { $sum: "$items.price"}
    }
    },
    { $set: { sales_price: { $toDouble: "$sales_price"}}},
    { $merge: { into: "monthlyPhoneTransactions", whenMatched: "replace" } }
    ]
    var monthlyPhoneTransactions = context.services.get("mongodb-atlas").db("sample_supplies").collection("sales");
    return monthlyPhoneTransactions.aggregate(pipeline);
    };
  3. 单击Function Editor右下角的Run按钮,创建monthlyPhoneTransactions物化视图。

    Function Editor底部的Result标签页应指示成功,没有任何错误。

  4. 单击 Save Draft(连接)。

4
  1. 在终端窗口中打开mongosh并连接到集群。有关连接的详细说明,请参阅通过mongosh连接。

  2. 使用sample_supplies数据库:

    use sample_supplies
  3. 查询sales集合。请注意, sales中的最后一次销售发生在2017的 12 月:

    db.sales.find().sort( {saleDate: -1} )
  4. 确认已在sample_supplies数据库中创建物化视图:

    show collections

    该命令会列出您的集合,包括新创建的monthlyPhoneTransactions物化视图。

  5. 查询monthlyPhoneTransactions物化视图:

    db.monthlyPhoneTransactions.find().sort( { _id: -1} )

    monthlyPhoneTransactions物化视图会显示新添加的数据。顶部结果反映了最近的事务发生在 12 月2017 。

在 App Services 用户界面中创建updateMonthlyPurchaseOrders函数。

updateMonthlyPurchaseOrders函数将每月累积采购订单信息添加到monthlyPhoneTransactions物化视图。该函数更新通过电话执行的采购订单的每月采购订单信息。

以下示例定义了该函数:

exports = function(){
var pipeline = [
{ $match: {purchaseMethod: "Phone"} },
{ $unwind: {path: "$items"}},
{ $group: {
_id: { $dateToString:
{ format: "%Y-%m", date: "$saleDate" } },
sales_quantity: { $sum: "$items.quantity"},
sales_price: { $sum: "$items.price"}
}},
{ $set: { sales_price: { $toDouble: "$sales_price"}}},
{ $merge: { into: "monthlyPhoneTransactions", whenMatched: "replace" } }
]
var monthlyPhoneTransactions = context.services.get("mongodb-atlas").db("sample_supplies").collection("purchaseOrders");
return monthlyPhoneTransactions.aggregate(pipeline);
};

updateMonthlyPurchaseOrders函数使用与updateMonthlySales函数相同的聚合管道阶段来更新monthlyPhoneTransactions

1

要从用户界面定义新的服务器端函数,请执行以下操作:

  1. 返回您的 App Services App。

  2. 单击左侧导航菜单中的 Functions(函数)。

  3. 单击 Create New Function(连接)。

  4. 输入updateMonthlyPurchaseOrders作为函数名称。

  5. Authentication 下,选择 System

2
  1. 单击 Function Editor 标签页。

  2. 将 JavaScript 代码添加到exports函数中。至少,代码必须将一个函数分配给全局变量exports

    exports = function(){
    var pipeline = [
    { $match: {purchaseMethod: "Phone"} },
    { $unwind: {path: "$items"}},
    { $group: {
    _id: { $dateToString:{ format: "%Y-%m", date: "$saleDate" } },
    sales_quantity: { $sum: "$items.quantity"},
    sales_price: { $sum: "$items.price"}
    }
    },
    { $set: { sales_price: { $toDouble: "$sales_price"}}},
    { $merge: { into: "monthlyPhoneTransactions", whenMatched: "replace" } }
    ]
    var monthlyPhoneTransactions = context.services.get("mongodb-atlas").db("sample_supplies").collection("purchaseOrders");
    return monthlyPhoneTransactions.aggregate(pipeline);
    };
  3. 单击Function Editor右下角的Run按钮,更新monthlyPhoneTransactions物化视图。

    Function Editor底部的Result标签页应指示成功,没有任何错误。

    updateMonthlyPurchaseOrders函数使用2018 1 月采购订单数据刷新monthlyPhoneTransactions物化视图。

  4. 单击 Save Draft(连接)。

3
  1. 返回mongosh并查询monthlyPhoneTransactions集合以确认更新:

    db.monthlyPhoneTransactions.find().sort( { _id: -1} )

    monthlyPhoneTransactions物化视图会显示新添加的数据。顶部结果反映了最近的事务发生在2018 1 月。

将上一步中创建的 App Services 函数安排为每天运行一次,以使物化视图保持最新状态。

1
2
3
用户界面字段名称
配置
Trigger Type
选择 Scheduled
Name
指定 updateMonthlySales
Schedule Type
  1. 选择 Basic

  2. 对于Repeat once by ,选择Day of the Month并将值设置为您的首选日期。

    注意

    或者,出于测试目的,将Repeat once by下拉列表设置为更频繁出现的项,例如MinuteHour

Select An Event Type
选择 Function
Function
选择 updateMonthlySales
4
5
6
7
用户界面字段名称
配置
Trigger Type
选择 Scheduled
Name
指定 updateMonthlyPurchaseOrders
Schedule Type
  1. 选择 Basic

  2. 对于Repeat once by ,选择Day of the Month并将值设置为您的首选日期。

    注意

    或者,出于测试目的,将Repeat once by下拉列表设置为更频繁出现的项,例如MinuteHour

Select An Event Type
选择 Function
Function
选择 updateMonthlyPurchaseOrders
8
9

monthlyPhoneTransactions 集合上创建 Atlas Search 索引。

1

点击 Atlas 左上角的 Database(数据库),导航到项目的 Database Deployments(数据库部署)页面。

2
3
4
5
6
  1. Index Name 字段中输入 monthlyPhoneTransactions

  2. Database and Collection(数据库和集合)部分中找到 sample_supplies 数据库,然后选择 monthlyPhoneTransactions 集合。

  3. 单击 Next(连接)。

7
8
9

此时将显示一个模态窗口,让您知道索引正在构建中。点击 Close 按钮。

10

新创建的索引会出现在 Atlas Search 标签页上。在构建索引期间,Status 字段显示为 Build in Progress。索引构建完成后,Status 字段将显示为Active

注意

较大的集合需要较长的索引时间。索引构建完成后,您将收到电子邮件通知。

针对新近更新和编制索引的monthlyPhoneTransactions集合运行查询。

1

在终端窗口中打开mongosh并连接到集群。有关连接的详细说明,请参阅通过mongosh连接。

2

mongosh提示符下运行以下命令:

use sample_supplies
3

以下查询计算 MonthlyPhoneTransactions 中总销售额大于或等于10000美元的月数:

db.monthlyPhoneTransactions.aggregate([
{
$search: {
"index": "monthlySalesIndex",
"range": {
"gt": 10000,
"path": ["sales_price"]
}
}
},
{
$count: 'months_w_over_10000'
},
])

上述查询返回4 ,表示monthlyPhoneTransactions物化视图的所有月份中只有4个月的总销售额大于或等于10000美元。此结果反映了来自sample_supplies.salessample_supplies.purchaseOrders集合的数据。

有关完整的聚合管道文档,请参阅《 MongoDB Server 手册》。

← 如何跨集合运行 Atlas 搜索查询