我如何只使用 Mongodb 聚合中的 return 某些字段($project),同时还使用 $match、$lookup 和 $filter
How do I only return SOME fields ($project) from Mongodb aggregation, while also using $match, $lookup AND $filter
我非常接近从这个查询中得到我想要的东西......但我只想要一些字段 returned 而现在它正在 returning 所有这些
注意:这是一个改进:我现在问如何return 只有某些字段,而我的类似 询问如何 return 数据 在开始日期和结束日期之间
此外,有人可以使用 MongoDB Playground 和我的数据集提供答案吗?这样我就可以试试了...我不太明白如何 "name"数据集让他们在操场上工作!
注册架构
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const RegisterSchema = new Schema({
userId: {type: Schema.Types.ObjectId, required: true},
accessToken: {type:String, required: true, default: null},
})
module.exports = Register = mongoose.model( 'register', RegisterSchema)
这是一些注册数据
[
{
"_id": "5eac9e815fc57b07f5d0d29f",
"userId": "5ea108babb65b800172b11be",
"accessToken": "111"
},
{
"_id": "5ecaeba3c7b910d3276df839",
"userId": "5e6c2dddad72870c84f8476b",
"accessToken": "222"
}
]
下一个文档包含通过 accessToken 与 Register 模式相关的数据
通知
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const NotificationSchema = new Schema({
accessToken: {type:String, required: true},
summaryId: {type:Number, required: true},
dateCreated: {type: Date, default: Date.now},
// I don't want these returned in the final results
dontWantThis1: {type:Number, required: true},
dontWantThis2: {type:Number, required: true},
})
module.exports = Notification = mongoose.model( 'notification', NotificationSchema)
这是一些通知数据
[{
"_id": "5ebf0390c719e60004f42e74",
"accessToken": "111",
"summaryId": 1111,
"dontWantThis1": 61,
"dontWantThis2": 62,
"dateCreated": "2020-04-17T00:00:00.000+00:00" },
{
"_id": "6ebf0390c719e60004f42e76",
"accessToken": "222",
"summaryId": 2221,
"dontWantThis1": 71,
"dontWantThis2": 72,
"dateCreated": "2020-04-18T00:00:00.000+00:00" },
{
"_id": "6ebf0390c719e60004f42e78",
"accessToken": "111",
"summaryId": 1112,
"dontWantThis1": 611,
"dontWantThis2": 622,
"dateCreated": "2020-05-25T00:00:00.000+00:00" },
{
"_id": "6ebf0390c719e60004f42e80",
"accessToken": "222",
"summaryId": 2222,
"dontWantThis1": 711,
"dontWantThis2": 722,
"dateCreated": "2020-05-26T00:00:00.000+00:00" }
]
有效,两个日期之间的 returns 数据,但是
此代码 return 包含所有内容,包括 'dontWantThis1' 和 'dontWantThis2'
注意
我不想要以 'dontWantThis' 开头的字段 - 但这只是为了显示我不想要的字段......我不是字面意思想要排除以 'dontWantThis' 开头的字段......它们可以命名为 'foo' 或 'apple' 或 'dog' 它们只是以这种方式命名以表明我不想要他们
// make sure the input dates are REALLY date objects
// I only want to see notifications for the month of May (in this example)
var dateStart = new Date('2020-05-01T00:00:00.000+00:00');
var dateEnd = new Date('2020-05-30T00:00:00.000+00:00');
var match = {$match: { userId: mongoose.Types.ObjectId(userId) } };
var lookup ={
$lookup:
{
from: "my_Notifications",
localField: "accessToken",
foreignField: "accessToken",
as: "notifications"
}
};
var dateCondition = { $and: [
{ $gte: [ "$$item.dateCreated", dateStart ] },
{ $lte: [ "$$item.dateCreated", dateEnd ] }
]}
var project = {
$project: {
notifications: {
$filter: {
input: "$notifications",
as: "item",
cond: dateCondition
} } }
};
var agg = [
match,
lookup,
project
];
Register.aggregate(agg)
.then( ..... )
尝试 1
我以为我可以做这样的事情,但它仍然 return所有通知字段
var project = {
$project: {
"_id": 1,
"userId": 1,
"accessToken":1,
"count":{$size:"$notifications"},
"notifications._id":1,
"notifications.summaryId": 1,
"notifications.dateCreated":1,
notifications : {
$filter: {
input: "$notifications",
as: "item",
cond: dateCondition
},
}}
};
解决方案
我创建了另一个投影并将其添加到管道中:
var project2 = {
$project: {
"_id": 1,
"userId": 1,
"accessToken":1,
"count":{$size:"$notifications"},
"notifications._id":1,
"notifications.summaryId": 1,
"notifications.dateCreated":1,
"notifications.dateProcessed":1,
}
};
var agg = [
match,
lookup,
project,
project2,
];
谢谢!!
https://whosebug.com/users/6635464/ngshravil-py 准确无误。
我创建了另一个投影:
var project2 = {
$project: {
"_id": 1,
"userId": 1,
"accessToken":1,
"count":{$size:"$notifications"},
"notifications._id":1,
"notifications.summaryId": 1,
"notifications.dateCreated":1,
"notifications.dateProcessed":1,
}
};
然后将其添加到我的聚合管道中:
var agg = [
match,
lookup,
project,
project2,
];
您需要使用 $dateFromString
和 $map
运算符将 notifications.dateCreated
转换为 ISODate
,因为您的日期是字符串形式。我建议你这样做,因为我不认为你可以用字符串格式进行日期比较。另外,请确保 dateStart
和 dateEnd
也应采用 ISODate
格式。
并且您需要两个 $project
运算符才能实现此目的。此外,我没有看到任何带有 userAccessToken
的字段,我假设它是 accessToken
。检查以下查询。
db.Register.aggregate([
{
$lookup: {
from: "my_Notifications",
localField: "accessToken",
foreignField: "accessToken",
as: "notifications"
}
},
{
$project: {
"_id": 1,
"userId": 1,
"accessToken": 1,
notifications: {
$map: {
input: "$notifications",
as: "n",
in: {
"_id": "$$n._id",
"summaryId": "$$n.summaryId",
"dateCreated": {
$dateFromString: {
dateString: "$$n.dateCreated"
}
}
}
}
}
}
},
{
$project: {
"userId": 1,
"accessToken": 1,
"notifications": {
$filter: {
input: "$notifications",
as: "item",
cond: {
$and: [
{
$gte: [
"$$item.dateCreated",
ISODate("2020-05-24T00:00:00Z")
]
},
{
$lte: [
"$$item.dateCreated",
ISODate("2020-05-26T00:00:00Z")
]
}
]
}
}
}
}
},
{
$set: {
"count": {
$size: "$notifications"
}
}
}
])
我非常接近从这个查询中得到我想要的东西......但我只想要一些字段 returned 而现在它正在 returning 所有这些
注意:这是一个改进:我现在问如何return 只有某些字段,而我的类似
此外,有人可以使用 MongoDB Playground 和我的数据集提供答案吗?这样我就可以试试了...我不太明白如何 "name"数据集让他们在操场上工作!
注册架构
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const RegisterSchema = new Schema({
userId: {type: Schema.Types.ObjectId, required: true},
accessToken: {type:String, required: true, default: null},
})
module.exports = Register = mongoose.model( 'register', RegisterSchema)
这是一些注册数据
[
{
"_id": "5eac9e815fc57b07f5d0d29f",
"userId": "5ea108babb65b800172b11be",
"accessToken": "111"
},
{
"_id": "5ecaeba3c7b910d3276df839",
"userId": "5e6c2dddad72870c84f8476b",
"accessToken": "222"
}
]
下一个文档包含通过 accessToken 与 Register 模式相关的数据
通知
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const NotificationSchema = new Schema({
accessToken: {type:String, required: true},
summaryId: {type:Number, required: true},
dateCreated: {type: Date, default: Date.now},
// I don't want these returned in the final results
dontWantThis1: {type:Number, required: true},
dontWantThis2: {type:Number, required: true},
})
module.exports = Notification = mongoose.model( 'notification', NotificationSchema)
这是一些通知数据
[{
"_id": "5ebf0390c719e60004f42e74",
"accessToken": "111",
"summaryId": 1111,
"dontWantThis1": 61,
"dontWantThis2": 62,
"dateCreated": "2020-04-17T00:00:00.000+00:00" },
{
"_id": "6ebf0390c719e60004f42e76",
"accessToken": "222",
"summaryId": 2221,
"dontWantThis1": 71,
"dontWantThis2": 72,
"dateCreated": "2020-04-18T00:00:00.000+00:00" },
{
"_id": "6ebf0390c719e60004f42e78",
"accessToken": "111",
"summaryId": 1112,
"dontWantThis1": 611,
"dontWantThis2": 622,
"dateCreated": "2020-05-25T00:00:00.000+00:00" },
{
"_id": "6ebf0390c719e60004f42e80",
"accessToken": "222",
"summaryId": 2222,
"dontWantThis1": 711,
"dontWantThis2": 722,
"dateCreated": "2020-05-26T00:00:00.000+00:00" }
]
有效,两个日期之间的 returns 数据,但是
此代码 return 包含所有内容,包括 'dontWantThis1' 和 'dontWantThis2'
注意
我不想要以 'dontWantThis' 开头的字段 - 但这只是为了显示我不想要的字段......我不是字面意思想要排除以 'dontWantThis' 开头的字段......它们可以命名为 'foo' 或 'apple' 或 'dog' 它们只是以这种方式命名以表明我不想要他们
// make sure the input dates are REALLY date objects
// I only want to see notifications for the month of May (in this example)
var dateStart = new Date('2020-05-01T00:00:00.000+00:00');
var dateEnd = new Date('2020-05-30T00:00:00.000+00:00');
var match = {$match: { userId: mongoose.Types.ObjectId(userId) } };
var lookup ={
$lookup:
{
from: "my_Notifications",
localField: "accessToken",
foreignField: "accessToken",
as: "notifications"
}
};
var dateCondition = { $and: [
{ $gte: [ "$$item.dateCreated", dateStart ] },
{ $lte: [ "$$item.dateCreated", dateEnd ] }
]}
var project = {
$project: {
notifications: {
$filter: {
input: "$notifications",
as: "item",
cond: dateCondition
} } }
};
var agg = [
match,
lookup,
project
];
Register.aggregate(agg)
.then( ..... )
尝试 1
我以为我可以做这样的事情,但它仍然 return所有通知字段
var project = {
$project: {
"_id": 1,
"userId": 1,
"accessToken":1,
"count":{$size:"$notifications"},
"notifications._id":1,
"notifications.summaryId": 1,
"notifications.dateCreated":1,
notifications : {
$filter: {
input: "$notifications",
as: "item",
cond: dateCondition
},
}}
};
解决方案
我创建了另一个投影并将其添加到管道中:
var project2 = {
$project: {
"_id": 1,
"userId": 1,
"accessToken":1,
"count":{$size:"$notifications"},
"notifications._id":1,
"notifications.summaryId": 1,
"notifications.dateCreated":1,
"notifications.dateProcessed":1,
}
};
var agg = [
match,
lookup,
project,
project2,
];
谢谢!!
https://whosebug.com/users/6635464/ngshravil-py 准确无误。
我创建了另一个投影:
var project2 = {
$project: {
"_id": 1,
"userId": 1,
"accessToken":1,
"count":{$size:"$notifications"},
"notifications._id":1,
"notifications.summaryId": 1,
"notifications.dateCreated":1,
"notifications.dateProcessed":1,
}
};
然后将其添加到我的聚合管道中:
var agg = [
match,
lookup,
project,
project2,
];
您需要使用 $dateFromString
和 $map
运算符将 notifications.dateCreated
转换为 ISODate
,因为您的日期是字符串形式。我建议你这样做,因为我不认为你可以用字符串格式进行日期比较。另外,请确保 dateStart
和 dateEnd
也应采用 ISODate
格式。
并且您需要两个 $project
运算符才能实现此目的。此外,我没有看到任何带有 userAccessToken
的字段,我假设它是 accessToken
。检查以下查询。
db.Register.aggregate([
{
$lookup: {
from: "my_Notifications",
localField: "accessToken",
foreignField: "accessToken",
as: "notifications"
}
},
{
$project: {
"_id": 1,
"userId": 1,
"accessToken": 1,
notifications: {
$map: {
input: "$notifications",
as: "n",
in: {
"_id": "$$n._id",
"summaryId": "$$n.summaryId",
"dateCreated": {
$dateFromString: {
dateString: "$$n.dateCreated"
}
}
}
}
}
}
},
{
$project: {
"userId": 1,
"accessToken": 1,
"notifications": {
$filter: {
input: "$notifications",
as: "item",
cond: {
$and: [
{
$gte: [
"$$item.dateCreated",
ISODate("2020-05-24T00:00:00Z")
]
},
{
$lte: [
"$$item.dateCreated",
ISODate("2020-05-26T00:00:00Z")
]
}
]
}
}
}
}
},
{
$set: {
"count": {
$size: "$notifications"
}
}
}
])