对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。
Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
MongoDB Branding Shape
Click here >
Docs 菜单

查询筛选条件、和检索对象数组

您可以使用 returnScope 选项设立查询上下文,并将对象数组作为单个文档返回。

要使用 returnScope 将嵌套对象作为独立文档检索,您必须:

returnScope 查询中包含以下语法:

{
$search: {
"<operator>": {
<operator-specification>,
},
"returnScope": {
"path": "<embedded-documents-field-to-retrieve>"
},
"returnStoredSource": true
}
}
{
$searchMeta: {
"returnScope": {
"path": "<embedded-documents-field-to-retrieve>"
},
"returnStoredSource": true
},
"facet": {
"<operator>": {
<operator-specification>,
},
"facets": {
<facet-definition>
}
}
}

要了解有关查询语法的更多信息,请参阅$search

returnScope 选项设置查询的检索上下文。如果您在查询中指定 returnScope,MongoDB Search 就会像处理单个文档一样对每个嵌入式文档进行评分、排序和计数。

当您使用 returnScope 选项时,MongoDB Search 仅返回您在 embeddedDocument 中配置为 storedSource 的字段。embeddedDocument 路径之外的字段(例如根级字段)和未配置为 storedSource 的字段不会被返回。

在操作符规范中,必须指定要查询的字段的完整路径。使用 returnScope 选项时,必须确保所有操作符规范路径都嵌套在 returnScope.path 下。要查询returnScope.path 之外的字段,必须使用 hasAncestorhasRoot操作符。要学习;了解详情,请参阅:

在查询中使用 returnScope 时,MongoDB Search 会填充 searchRootDocumentId 元数据字段。您可以在运行 MongoDB 8.3 或更高版本的集群上使用 searchRootDocumentId 元数据字段。此字段包含每个返回的嵌入式文档所在的根文档的标识符。要预计此值,请将 $meta 表达式与 searchRootDocumentId 关键字一起使用。

MongoDB Search 仅当您的查询同时设置 returnStoredSource: truereturnScope.path 时才填充 searchRootDocumentId。如果您在查询中引用 searchRootDocumentId,但查询未指定 returnScope,则查询将失败并显示以下错误:

query requires $search root document id metadata, but it is not
available

如果您想进行以下操作,请使用 searchRootDocumentId

  • 在对子文档进行过滤后,从父文档中获取字段。

  • 按父文档对子文档进行分组。

如果出现以下情况,请勿使用 searchRootDocumentId

  • 您只需要匹配的子文档中的字段。

  • 您希望返回结果集中每个子文档的父文档,因为这可能会很耗时。

以下示例演示了如何在查询中使用 returnScope 选项。这些示例使用 sample_training.companies 示例数据集。如果您在集群上加载数据并在集合的字段上创建示例索引,则可以针对示例数据运行以下查询。

1{
2 "mappings": {
3 "dynamic": false,
4 "fields": {
5 "funding_rounds": {
6 "type": "embeddedDocuments",
7 "dynamic": true,
8 "fields": {
9 "investments": {
10 "type": "embeddedDocuments",
11 "dynamic": true
12 }
13 },
14 "storedSource": {
15 "include": [
16 "round_code",
17 "raised_currency_code",
18 "raised_amount",
19 "investments.person",
20 "investments.financial_org"
21 ]
22 }
23 }
24 }
25 }
26}

前面的索引定义将MongoDB 搜索配置为:

  • funding_roundsfunding_rounds.investments 字段作为 embeddedDocuments 类型进行索引。

  • 为嵌套在 funding_roundsfunding_rounds.investments 对象数组中的所有可动态索引的字段建立索引。

  • 将以下字段存储在 mongot 上:

    • funding_rounds.round_code

    • funding_rounds.raised_currency_code

    • funding_rounds.raised_amount

    • funding_rounds.investments.person

    • funding_rounds.investments.financial_org

您可以使用embeddedDocument 操作符funding_roundsfunding_rounds.investments 字段进行逐元素查询。以下章节展示了一些使用 returnScope 选项将 embeddedDocuments 字段作为单独文档检索的示例查询。

来自 sample_training.companies 集合的示例文档结构
{
...,
"funding_rounds": [
{
"id": <integer>,
"round_code": "<string>",
"source_url": "<string>",
"source_description": "<string>",
"raised_amount": <integer>,
"raised_currency_code": "<string>",
"funded_year": <integer>,
"funded_month": "<string>",
"funded_day": "<string>",
"investments": [
{
"company": "<string>",
"financial_org": {
"name": "<string>",
"permalink": "<string>"
},
"person": {
"first_name": "<string>",
"last_name": "<string>",
"permalink": "<string>"
}
},
...
]
},
...
],
...
}

以下各节演示了使用 returnScope 选项检索存储在 mongot 上的 embeddedDocuments 类型字段的示例查询。

查询和检索嵌入式文档字段。

以下查询使用 range(MongoDB搜索操作符)funding_rounds.raised_amount 字段中查询大于和等于 5000000 且小于和等于 10000000 的金额。它使用 returnScope 选项查询范围设置为 funding_rounds字段。它返回 funding_rounds 对象数组中存储的所有字段,包括使用 returnStoredSource 选项存储的 funding_rounds.investments 对象数组中的字段。它将结果数量限制为仅包含 5funding_rounds 文档。

1db.companies.aggregate(
2 {
3 "$search": {
4 "range": {
5 "path": "funding_rounds.raised_amount",
6 "gte": 5000000,
7 "lte": 10000000
8 },
9 "returnStoredSource": true,
10 "returnScope": {
11 "path": "funding_rounds"
12 }
13 }
14 },
15 {
16 "$limit": 5
17 }
18)
[
{
round_code: 'a',
raised_amount: 5250000,
raised_currency_code: 'USD',
investments: [
{
financial_org: {
name: 'Frazier Technology Ventures',
permalink: 'frazier-technology-ventures'
},
person: null
},
{
financial_org: { name: 'Trinity Ventures', permalink: 'trinity-ventures' },
person: null
}
]
},
{
round_code: 'b',
raised_amount: 9500000,
raised_currency_code: 'USD',
investments: [
{
financial_org: { name: 'Accel Partners', permalink: 'accel-partners' },
person: null
},
{
financial_org: {
name: 'Frazier Technology Ventures',
permalink: 'frazier-technology-ventures'
},
person: null
},
{
financial_org: { name: 'Trinity Ventures', permalink: 'trinity-ventures' },
person: null
}
]
},
{
round_code: 'a',
raised_amount: 5000000,
raised_currency_code: 'USD',
investments: [
{
financial_org: {
name: 'Charles River Ventures',
permalink: 'charles-river-ventures'
},
person: null
},
{
financial_org: {
name: 'Union Square Ventures',
permalink: 'union-square-ventures'
},
person: null
},
{
financial_org: null,
person: {
first_name: 'Marc',
last_name: 'Andreessen',
permalink: 'marc-andreessen'
}
},
{
financial_org: null,
person: {
first_name: 'Dick',
last_name: 'Costolo',
permalink: 'dick-costolo'
}
},
{
financial_org: null,
person: {
first_name: 'Naval',
last_name: 'Ravikant',
permalink: 'naval-ravikant'
}
},
{
financial_org: null,
person: {
first_name: 'Ron',
last_name: 'Conway',
permalink: 'ron-conway'
}
},
{
financial_org: null,
person: {
first_name: 'Chris',
last_name: 'Sacca',
permalink: 'chris-sacca'
}
},
{
financial_org: null,
person: {
first_name: 'Greg',
last_name: 'Yaitanes',
permalink: 'greg-yaitanes'
}
},
{
financial_org: null,
person: {
first_name: 'Brian',
last_name: 'Pokorny',
permalink: 'brian-pokorny'
}
},
{
financial_org: { name: 'SV Angel', permalink: 'sv-angel' },
person: null
}
]
},
{
round_code: 'e',
raised_amount: 5166511,
raised_currency_code: 'USD',
investments: []
},
{
round_code: 'b',
raised_amount: 9000000,
raised_currency_code: 'USD',
investments: [
{
financial_org: {
name: 'Charles River Ventures',
permalink: 'charles-river-ventures'
},
person: null
},
{
financial_org: { name: 'Redpoint Ventures', permalink: 'redpoint-ventures' },
person: null
},
{
financial_org: {
name: 'The Kinsey Hills Group',
permalink: 'kinsey-hills-group'
},
person: null
}
]
}
]

查询并检索多个嵌入式文档字段。

以下查询使用 compound 操作符在同一查询中搜索多层嵌套 embeddedDocuments 字段:

  • 必须与 ``funding_rounds.raised_currency_code`` 匹配与 USD

  • 应将 funding_rounds.investments.financial_org.nameTrinity Ventures 匹配

它会返回 funding_rounds 对象数组内存储的所有字段,包括 funding_rounds.investments 中的字段。它将结果数量限制为 5 funding_rounds 文档。

1db.companies.aggregate(
2 {
3 "$search": {
4 "compound": {
5 "must": [{
6 "text": {
7 "path": "funding_rounds.raised_currency_code",
8 "query": "usd"
9 }
10 }],
11 "should": [{
12 "phrase": {
13 "path": "funding_rounds.investments.financial_org",
14 "query": "Trinity Ventures",
15 }
16 }]
17 },
18 "returnStoredSource": true,
19 "returnScope": {
20 "path": "funding_rounds"
21 }
22 }
23 },
24 {
25 "$limit": 5
26 }
27)
[
{
round_code: 'a',
raised_amount: 5250000,
raised_currency_code: 'USD',
investments: [
{
financial_org: {
name: 'Frazier Technology Ventures',
permalink: 'frazier-technology-ventures'
},
person: null
},
{
financial_org: { name: 'Trinity Ventures', permalink: 'trinity-ventures' },
person: null
}
]
},
{
round_code: 'b',
raised_amount: 9500000,
raised_currency_code: 'USD',
investments: [
{
financial_org: { name: 'Accel Partners', permalink: 'accel-partners' },
person: null
},
{
financial_org: {
name: 'Frazier Technology Ventures',
permalink: 'frazier-technology-ventures'
},
person: null
},
{
financial_org: { name: 'Trinity Ventures', permalink: 'trinity-ventures' },
person: null
}
]
},
{
round_code: 'c',
raised_amount: 25000000,
raised_currency_code: 'USD',
investments: [
{
financial_org: { name: 'DAG Ventures', permalink: 'dag-ventures' },
person: null
},
{
financial_org: { name: 'Accel Partners', permalink: 'accel-partners' },
person: null
},
{
financial_org: { name: 'Trinity Ventures', permalink: 'trinity-ventures' },
person: null
},
{
financial_org: {
name: 'Frazier Technology Ventures',
permalink: 'frazier-technology-ventures'
},
person: null
}
]
},
{
round_code: 'angel',
raised_amount: 500000,
raised_currency_code: 'USD',
investments: [
{
financial_org: null,
person: {
first_name: 'Peter',
last_name: 'Thiel',
permalink: 'peter-thiel'
}
},
{
financial_org: null,
person: {
first_name: 'Reid',
last_name: 'Hoffman',
permalink: 'reid-hoffman'
}
}
]
},
{
round_code: 'a',
raised_amount: 12700000,
raised_currency_code: 'USD',
investments: [
{
financial_org: { name: 'Accel Partners', permalink: 'accel-partners' },
person: null
},
{
financial_org: null,
person: {
first_name: 'Mark',
last_name: 'Pincus',
permalink: 'mark-pincus'
}
},
{
financial_org: null,
person: {
first_name: 'Reid',
last_name: 'Hoffman',
permalink: 'reid-hoffman'
}
}
]
}
]

使用 searchRootDocumentId 元字段按父级对子级进行分组。

以下查询使用 range (MongoDB Search 操作符) 查询 funding_rounds.raised_amount 字段中大于或等于 5000000 且小于或等于 10000000 的金额。它使用 returnScope 选项将查询范围设置为 funding_rounds 字段。它使用 searchRootDocumentId 元字段作为分组密钥,将每个母公司下的匹配 funding_rounds 分组在一起,并计算 avgRaisedAmount 字段中每家公司的平均 raised_amount。它按 avgRaisedAmount 降序排序结果,并将结果数限制为 10 家公司。

1db.companies.aggregate([
2 {
3 "$search": {
4 "returnStoredSource": true,
5 "returnScope": {
6 "path": "funding_rounds"
7 },
8 "range": {
9 "path": "funding_rounds.raised_amount",
10 "gte": 5000000,
11 "lte": 10000000
12 }
13 }
14 },
15 {
16 "$group": {
17 "_id": { "$meta": "searchRootDocumentId" },
18 "funding_rounds": {
19 "$push": {
20 "round_code": "$round_code",
21 "raised_amount": "$raised_amount",
22 "raised_currency_code": "$raised_currency_code"
23 }
24 },
25 "avgRaisedAmount": { "$avg": "$raised_amount" }
26 }
27 },
28 { "$sort": { "avgRaisedAmount": -1 } },
29 { "$limit": 10 }
30])
[
{
_id: ObjectId('52cdef7d4bab8bd675298f82'),
funding_rounds: [
{
round_code: 'a',
raised_amount: 10000000,
raised_currency_code: 'USD'
}
],
avgRaisedAmount: 10000000
},
{
_id: ObjectId('52cdef7e4bab8bd67529af80'),
funding_rounds: [
{
round_code: 'b',
raised_amount: 10000000,
raised_currency_code: 'USD'
}
],
avgRaisedAmount: 10000000
},
{
_id: ObjectId('52cdef7f4bab8bd67529be3d'),
funding_rounds: [
{
round_code: 'a',
raised_amount: 10000000,
raised_currency_code: 'USD'
}
],
avgRaisedAmount: 10000000
},
{
_id: ObjectId('52cdef7f4bab8bd67529c52d'),
funding_rounds: [
{
round_code: 'unattributed',
raised_amount: 10000000,
raised_currency_code: 'USD'
}
],
avgRaisedAmount: 10000000
},
{
_id: ObjectId('52cdef7e4bab8bd67529ab31'),
funding_rounds: [
{
round_code: 'c',
raised_amount: 10000000,
raised_currency_code: 'USD'
},
{
round_code: 'a',
raised_amount: 10000000,
raised_currency_code: 'USD'
}
],
avgRaisedAmount: 10000000
},
{
_id: ObjectId('52cdef7e4bab8bd67529aa94'),
funding_rounds: [
{
round_code: 'b',
raised_amount: 10000000,
raised_currency_code: 'USD'
}
],
avgRaisedAmount: 10000000
},
{
_id: ObjectId('52cdef7f4bab8bd67529be6f'),
funding_rounds: [
{
round_code: 'a',
raised_amount: 10000000,
raised_currency_code: 'USD'
}
],
avgRaisedAmount: 10000000
},
{
_id: ObjectId('52cdef7c4bab8bd6752985cb'),
funding_rounds: [
{
round_code: 'd',
raised_amount: 10000000,
raised_currency_code: 'USD'
}
],
avgRaisedAmount: 10000000
},
{
_id: ObjectId('52cdef7d4bab8bd675299fd1'),
funding_rounds: [
{
round_code: 'c',
raised_amount: 10000000,
raised_currency_code: 'USD'
}
],
avgRaisedAmount: 10000000
},
{
_id: ObjectId('52cdef7f4bab8bd67529c2c8'),
funding_rounds: [
{
round_code: 'debt_round',
raised_amount: 10000000,
raised_currency_code: 'USD'
}
],
avgRaisedAmount: 10000000
}
]

在过滤嵌入式文档字段后,从父文档中检索字段。

以下查询使用 range (MongoDB Search Operator) 查询 funding_rounds.raised_amount 字段中大于等于 5000000 且小于等于 10000000 的金额。它使用 returnScope 选项将查询范围设置为 funding_rounds 字段。它按 raised_amount 降序排序匹配的 funding_rounds ,并将结果限制为前 10 轮融资。然后,它使用 searchRootDocumentId 元字段将每轮融资连接回 companies 集合中的母公司,并返回公司的 name 以及融资轮的 round_coderaised_amountraised_currency_code 字段。

1db.companies.aggregate([
2 {
3 "$search": {
4 "returnStoredSource": true,
5 "returnScope": {
6 "path": "funding_rounds"
7 },
8 "range": {
9 "path": "funding_rounds.raised_amount",
10 "gte": 5000000,
11 "lte": 10000000
12 }
13 }
14 },
15 { "$sort": { "raised_amount": -1 } },
16 { "$limit": 10 },
17 { "$addFields": { "root_id": { "$meta": "searchRootDocumentId" } } },
18 {
19 "$lookup": {
20 "from": "companies",
21 "localField": "root_id",
22 "foreignField": "_id",
23 "as": "company"
24 }
25 },
26 { "$unwind": "$company" },
27 {
28 "$project": {
29 "_id": 0,
30 "round_code": 1,
31 "raised_amount": 1,
32 "raised_currency_code": 1,
33 "company.name": 1
34 }
35 }
36])
[
{
round_code: 'partial',
raised_amount: 10000000,
raised_currency_code: 'USD',
company: { name: 'WeFi' }
},
{
round_code: 'b',
raised_amount: 10000000,
raised_currency_code: 'USD',
company: { name: 'LinkedIn' }
},
{
round_code: 'a',
raised_amount: 10000000,
raised_currency_code: 'USD',
company: { name: 'Lotame' }
},
{
round_code: 'c',
raised_amount: 10000000,
raised_currency_code: 'USD',
company: { name: 'OpenX' }
},
{
round_code: 'b',
raised_amount: 10000000,
raised_currency_code: 'USD',
company: { name: 'AddThis' }
},
{
round_code: 'a',
raised_amount: 10000000,
raised_currency_code: 'USD',
company: { name: 'Terabitz' }
},
{
round_code: 'b',
raised_amount: 10000000,
raised_currency_code: 'USD',
company: { name: 'Six Apart' }
},
{
round_code: 'a',
raised_amount: 10000000,
raised_currency_code: 'USD',
company: { name: 'Snocap' }
},
{
round_code: 'b',
raised_amount: 10000000,
raised_currency_code: 'USD',
company: { name: 'Wikia' }
},
{
round_code: 'unattributed',
raised_amount: 10000000,
raised_currency_code: 'USD',
company: { name: 'Mashery' }
}
]