译自:http://docs.mongoing.com/manual-zh/reference/operator/aggregation/redact.html
http://www.myexception.cn/go/2046467.html
$redact
根据字段所处的document结构的级别,对文档进行“修剪”,它通常和“判断语句if-else”结合使用即“$cond”。$redact可选值有3个:
1)$$DESCEND:包含当前document级别的所有fields。当前级别字段的内嵌文档将会被继续检测。
2)$$PRUNE:不包含当前文档或者内嵌文档级别的所有字段,不会继续检测此级别的其他字段,即使这些字段的内嵌文档持有相同的访问级别。
3)$$KEEP:包含当前文档或内嵌文档级别的所有字段,不再继续检测此级别的其他字段,即使这些字段的内嵌文档中持有不同的访问级别。
{
_id: 1,
tags: [ "G", "STLW" ],
year: 2014,
subsections: [
{
subtitle: "Section 1",
tags: [ "SI", "G" ],
},
{
subtitle: "Section 2",
tags: [ "STLW" ],
},
{
subtitle: "Section 3",
tags: [ "TK" ],
content: {
tags: [ "HCS" ]
}
}
]
}
那么对于语句:
$redact: {$cond: {
if: {
$gt: [ { $size: { $setIntersection: [ "$tags", ["STLW","G"] ] } }, 0 ] },
then: "$$DESCEND",
else: "$$PRUNE"
}
}
$setIntersection表示将2个数组的交集中不同元素的个数,$cond就是一个三元表达式,此例中表示“如果交集元素的个数大于0,则值为为$$DESCEND,否则为$$PRUNE”。对于此文档(ROOT级别)的最高级别的tags值为["G","STLW"],此级别值为$$DESCEND,即此tage同级别的其他字段将会包含;那么继续检测“subsections.tags”级别的所有文档(是个数组,则逐个检测),基本思路类似,如果此级别返回$$DECEND那么继续检测“subsections.tags.content.tags”是否符合访问规则,如果返回$$PRUNE,那么此tags所在的内嵌文档的所有字段将被排除,即使与此tags同级别的contents.tags符合访问规则。最终输出结果:
{
"_id" : 1,
"tags" : [ "G", "STLW" ],
"year" : 2014,
"subsections" : [
{
"subtitle" : "Section 1",
"tags" : [ "SI", "G" ],
"content" : "Section 1"
},
{
"subtitle" : "Section 2: Analysis",
"tags" : [ "STLW" ],
"content" : "Section 2"
}
]
}
再如如下例子:
db.accounts.find({})的查询结果如下:
{
"_id" : 1.0,
"level" : 1.0,
"acct_id" : "xyz123",
"cc" : {
"level" : 5.0,
"type" : "yy",
"num" : 0.0,
"exp_date" : ISODate("2015-11-01T00:00:00.000+0000"),
"billing_addr" : {
"level" : 5.0,
"addr1" : "123 ABC Street",
"city" : "Some City"
},
"shipping_addr" : [
{
"level" : 3.0,
"addr1" : "987 XYZ Ave",
"city" : "Some City"
},
{
"level" : 3.0,
"addr1" : "PO Box 0123",
"city" : "Some City"
}
]
},
"status" : "A"
}
db.accounts.aggregate(
[
{ $match: { status: "A" } },
{
$redact: {
$cond: {
if: { $eq: [ "$level", 5 ] },
then: "$$PRUNE",
else: "$$DESCEND"
}
}
}
]
);
的查询结果如下:
{
"_id" : 1.0,
"level" : 1.0,
"acct_id" : "xyz123",
"status" : "A"
}