您可以使用 returnScope 选项设立查询上下文,并将对象数组作为单个文档返回。
要求
要使用 returnScope 将嵌套对象作为独立文档检索,您必须:
将对象数组索引为 embeddedDocuments 类型。
为要检索的嵌套字段定义 storedSource。MongoDB 搜索仅返回在
storedSource中定义的字段。在查询中将 returnStoredSource 选项设置为
true。
语法
returnScope 查询中包含以下语法:
要了解有关查询语法的更多信息,请参阅$search 。
行为
returnScope 选项设置查询的检索上下文。如果您在查询中指定 returnScope,MongoDB Search 就会像处理单个文档一样对每个嵌入式文档进行评分、排序和计数。
Considerations
当您使用 returnScope 选项时,MongoDB Search 仅返回您在 embeddedDocument 中配置为 storedSource 的字段。embeddedDocument 路径之外的字段(例如根级字段)和未配置为 storedSource 的字段不会被返回。
在操作符规范中,必须指定要查询的字段的完整路径。使用 returnScope 选项时,必须确保所有操作符规范路径都嵌套在 returnScope.path 下。要查询returnScope.path 之外的字段,必须使用 hasAncestor 或 hasRoot操作符。要学习;了解详情,请参阅:
检索根文档 ID
When you use returnScope in a query, MongoDB Search populates a searchRootDocumentId metadata field. You can use the searchRootDocumentId metadata field on clusters running MongoDB 8.3 or later. This field contains the identifier of the root document that contains each returned embedded document. To project this value, use the $meta expression with the searchRootDocumentId keyword.
MongoDB Search 仅当您的查询同时设置 returnStoredSource: true 和 returnScope.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_rounds和funding_rounds.investments字段作为embeddedDocuments类型进行索引。为嵌套在
funding_rounds和funding_rounds.investments对象数组中的所有可动态索引的字段建立索引。将以下字段存储在
mongot上:funding_rounds.round_codefunding_rounds.raised_currency_codefunding_rounds.raised_amountfunding_rounds.investments.personfunding_rounds.investments.financial_org
您可以使用embeddedDocument 操作符对 funding_rounds 和 funding_rounds.investments 字段进行逐元素查询。以下章节展示了一些使用 returnScope 选项将 embeddedDocuments 字段作为单独文档检索的示例查询。
{ ..., "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 对象数组中的字段。它将结果数量限制为仅包含 5 个 funding_rounds 文档。
1 db.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.name与Trinity Ventures匹配
它会返回 funding_rounds 对象数组内存储的所有字段,包括 funding_rounds.investments 中的字段。它将结果数量限制为 5 funding_rounds 文档。
1 db.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' } } ] } ]
以下查询使用 range (MongoDB Search 操作符) 查询 funding_rounds.raised_amount 字段中大于或等于 5000000 且小于或等于 10000000 的金额。它使用 returnScope 选项将查询范围设置为 funding_rounds 字段。它使用 searchRootDocumentId 元字段作为分组密钥,将每个母公司下的匹配 funding_rounds 分组在一起,并计算 avgRaisedAmount 字段中每家公司的平均 raised_amount。它按 avgRaisedAmount 降序排序结果,并将结果数限制为 10 家公司。
1 db.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_code、raised_amount 和 raised_currency_code 字段。
1 db.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' } } ]