Docs 菜单
Docs 主页
/
MongoDB Atlas
/ / /

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

在此页面上

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

本教程介绍如何创建索引并针对 示例数据集和新 sample_supplies.purchaseOrders 中的 sample_supplies.sales 集合运行查询。

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

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

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

  2. 创建两个定时触发器:

    • updateMonthlySales,带有一个名为 updateMonthlySales 的函数,该函数使用示例 sample_supplies.sales 集合中的数据初始化 monthlyPhoneTransactions 物化视图。

    • updateMonthlyPurchaseOrders,其中包含一个名为 updateMonthlyPurchaseOrders 的函数,该函数使用 sample_supplies.purchaseOrders 集合中的数据来更新 monthlyPhoneTransactions 物化视图。

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

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

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

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

要创建触发器,您必须拥有 Project Owner 或更高的项目访问权限。

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

  2. 使用 sample_supplies 数据库:

    use sample_supplies
2

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

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} )
{
_id: ObjectId("62434c07d574cd0ce200ba75"),
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'
},
{
_id: ObjectId("62434c07d574cd0ce200ba74"),
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'
}

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

在以下过程中,您将创建触发器以创建物化视图,并安排函数每天更新物化视图。

1
  1. 如果尚未显示,请从导航栏上的 Organizations 菜单中选择包含项目的组织。

  2. 如果尚未显示,请从导航栏的 Projects 菜单中选择您的项目。

  3. 在侧边栏中,单击 Services 标题下的 Triggers

    会显示触发器页面。

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
4

此触发器的函数定义了一个 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 会将聚合结果中的文档插入到阶段指定的集合中。

5

单击 Function Editor 右下角的 Run 按钮创建 monthlyPhoneTransactions 物化视图。

Function Editor 底部的 Result 标签页反映了函数的执行状态。单击 Save Draft

1
  1. 如果尚未显示,请从导航栏上的 Organizations 菜单中选择包含项目的组织。

  2. 如果尚未显示,请从导航栏的 Projects 菜单中选择您的项目。

  3. 在侧边栏中,单击 Services 标题下的 Triggers

    会显示触发器页面。

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

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

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

4

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

5

单击 Function Editor 右下角的 Run 按钮以更新 monthlyPhoneTransactions 物化视图。

Function Editor 底部的 Result 标签页反映了该函数的执行状态。

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

6
7
8

使用 mongosh 查询 monthlyPhoneTransactions 集合以确认更新:

db.monthlyPhoneTransactions.find().sort( { _id: -1} )
{
_id: '2018-01',
sales_quantity: 66,
sales_price: Decimal128("1407.10")
}

monthlyPhoneTransactions 物化视图显示新添加的数据。排在前面的结果显示最近的交易发生在 2018 年 1 月。

9

monthlyPhoneTransactions 集合上创建 Atlas Search 索引。

1
  1. 如果尚未显示,请从导航栏上的 Organizations 菜单中选择包含所需项目的组织。

  2. 如果尚未显示,请从导航栏的Projects菜单中选择所需的项目。

  3. 如果尚未出现,请单击侧边栏中的 Clusters(部署)。

    会显示集群页面。

2

您可以从侧边栏、 Data Explorer 或集群详细信息页面转到 Atlas Search 页面。

  1. 在侧边栏中,单击 Services 标题下的 Atlas Search

  2. Select data source 下拉菜单中选择您的集群并单击 Go to Atlas Search

    将显示 Atlas Search 页面。

  1. 单击集群的对应 Browse Collections 按钮。

  2. 展开数据库并选择集合。

  3. 单击该集合的 Search Indexes 标签页。

    将显示 Atlas Search 页面。

  1. 单击集群的名称。

  2. 单击 Atlas Search 标签页。

    将显示 Atlas Search 页面。

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

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

  3. 单击 Next(连接)。

6
7
8

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

9

新创建的索引会出现在 Atlas Search 标签页上。在构建索引期间,Status 字段显示为 Building。索引构建完成后,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 服务器手册。

后退

跨集合