提问人:BreenDeen 提问时间:11/10/2023 最后编辑:BreenDeen 更新时间:11/14/2023 访问量:130
如何使用聚合管道查找未在售但存在于产品详细信息集合中的产品的 ID
How to find ids for products that are not on sale but exist in the product details collection using aggregation pipeline
问:
我正在加入 productDetail 集合上的产品集合,其中产品_id是 productDetail 集合中的_id。我希望能够找到未在售但存在于 productDetail 表中的产品,以作为 inProductDetailCollection 包含在我的输出中,以便进行报告。我试了一下,但它不起作用。即使某些_ids不在 productDetail 表中,它也始终返回 true。这是我的尝试。我怎样才能让它将标志 inProductDetailCollection 设置为 false(如果缺失)或 true(如果存在)
db.getCollection("products").aggregate([
{
"$match": {
"onSale": {
"$exists": false
}
}
},
{
"$lookup": {
"from": "productDetail",
"localField": "_id",
"foreignField": "_id",
"as": "productDetail"
}
},
{
"$match": {
"$expr": {
"$eq": [
"$productDetail",
[]
]
}
}
},
{
"$unwind": {
"path": "$productDetail",
"preserveNullAndEmptyArrays": true
}
},
{
"$addFields": {
"onSale": false
}
},
{
"$group": {
"_id": {
"productId": "$_id",
"onSale": "$onSale"
}
}
},
{
"$project": {
"productId": "$_id.productId",
"onSale": "$_id.onSale",
"inProductDetailCollection":
{
$cond: { if: { $gt: [ "_id", 0 ] }, then: true, else: false }
},
"_id": 0
}
}
]
)
下面是数据示例。需要注意的一点是,productDetail 表中的产品可能没有_ids,因为此表是由夜间批处理作业上传的。此外,未打折的商品将没有“onSale”: “Y” 属性。数据如下所示:
//products collection, some fields omitted for brevity
[
{
"_id": 123345,
"name": "NutraFast",
"description": "Supplement",
"price": 35.99
},
{
"_id": 13443,
"name": "BerryBlast",
"description": "Athletes Sports Drink",
"price": 12.99
},
{
"_id": 15644
"name": "MagnoPower-11",
"description": "Supplement",
"price": 45.99
}
,{
"_id": 17011
"name": "Zinc566",
"description": "Supplement",
"price": 25.99
},
{
"_id": 15011
"name": "VitaMax",
"description": "Supplement",
"price": 15.99
},
{
"_id": 15311
"name": "VitaMax",
"description": "Supplement",
"price": 15.99
},
{
"_id": 15316
"name": "Chlorphyl Cleanse",
"description": "Supplement",
"price": 55.99
}
]
下面是 productDetail 集合示例
//productDetail collection
[
{
"_id": 123345,
"discount": 0.3,
"amount-per-unit": 50,
"inStock": "Y"
},
{
"_id": 13443,
"discount": 0.5,
"onSale": "Y",
"amount-per-unit": 60,
"inStock": "Y"
"onSale":"Y"
},
{
"_id" : 15644,
"discount": 0.5,
"onSale": "Y",
"amount-per-unit": 60,
"inStock": "Y"
},
{
"_id" : 15011,
"discount": 0.5,
"amount-per-unit": 60,
"inStock": "Y"
},
{
"_id" : 17011,
"discount": 0.5,
"amount-per-unit": 60,
"inStock": "Y"
}
]
答:
很难理解你真正需要什么。但是,我冒昧地更正了示例文档中的一些无效对象结构,以下是两种可能的聚合,希望能为您提供所需的输出:
示例 1
这将仅返回具有以下条件的文档:products
- 匹配
productDetail
- 使用包含文档的名为
productDetail
$lookup
- 带有名为
inProductDetailCollectionButNotOnSale
- 这只有在不打折的情况下才会出现
true
product
- 或其他方式
false
db.getCollection("products").aggregate([
{
$lookup: {
from: "productDetail",
localField: "_id",
foreignField: "_id",
as: "productDetail"
}
},
{
$unwind: {
path: "$productDetail"
}
},
{
$set: {
inProductDetailCollectionButNotOnSale: {
$cond: [
{
$eq: [
"$productDetail.onSale",
"Y"
]
},
false,
true
]
}
}
}
])
有关工作示例,请参见 此处。
示例 2
这将返回所有文件,包括:products
- 包含文档(如果有)的字段
productDetail
$lookup
- 带有名为
inProductDetailCollectionButNotOnSale
- 只有当有匹配并且不打折时才会有
true
product
productDetail
- 或其他方式
false
db.getCollection("products").aggregate([
{
$lookup: {
from: "productDetail",
localField: "_id",
foreignField: "_id",
as: "productDetail"
}
},
{
$unwind: {
path: "$productDetail",
preserveNullAndEmptyArrays: true
}
},
{
$set: {
inProductDetailCollectionButNotOnSale: {
$cond: [
{
$and: [
{
$gt: [
"$productDetail",
0
]
},
{
$ne: [
"$productDetail.onSale",
"Y"
]
}
]
},
true,
false
]
}
}
}
])
有关工作示例,请参见 此处。
注意:为清楚起见,如果其他人想知道为什么这部分工作:
$gt: [
"$productDetail",
0
]
Mongodb 有一个比较/排序顺序,它按从低到高的顺序列出 BSON 类型。我所做的是将该字段与 .由于在列表中排名第 4 位,在列表中排名第 3,这基本上意味着如果文档中存在,那么它将位于第 4 级,高于 () 高于列表中第 3 级的数字零。$productDetail
Number
Object
Number
$productDetail
$gt
它返回 true,因为它实质上转换为:
$gt: [
4, // 4 is greater than 3
3
]
如果不存在,则它将返回 false,因为 a 位于第 2 级,而高于第 3 级,因此它转换为:$productDetail
null
Number
$gt: [
2, // 2 is NOT greater than 3
3
]
评论
products
productDetail
product
productDetail
_id