MongoDB 使用 mongoose 填充一个字段并计算嵌套布尔字段中的总 'true' 个值
MongoDB populate a field and count total 'true' values in nested boolean fields using mongoose
我有两个mongo结构文件
链接文档
{
"_id": {
"$oid": "6002d2d627925c4194a15a94"
},
"visit_count": 20,
"password": null,
"password_protected": false,
"description": null,
"analytics": [
{
"$oid": "6002d568e9c7d24d34413492"
},
{
"$oid": "6002d612464785401824a782"
}
],
"alias": "g",
"short_url": "https://reduced.me/g",
"long_url": "https://google.com",
"created": {
"$date": "2021-01-16T11:49:42.517Z"
},
"__v": 2
}
分析文档
[
{
"_id": {
"$oid": "6002d568e9c7d24d34413492"
},
"os": {
"windows": true,
"linux": false,
"mac": false,
"android": false
},
"browser": {
"opera": false,
"ie": false,
"edge": false,
"safari": false,
"firefox": true,
"chrome": false
},
"details": {
"os": "Windows 10.0",
"browser": "Edge",
"version": "87.0.664.75",
"platform": "Microsoft Windows",
"source": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 Edg/87.0.664.75"
},
"__v": 0
},
{
"_id": {
"$oid": "6002d612464785401824a782"
},
"os": {
"windows": true,
"linux": false,
"mac": false,
"android": false
},
"browser": {
"opera": false,
"ie": false,
"edge": true,
"safari": false,
"firefox": false,
"chrome": false
},
"details": {
"os": "Windows 10.0",
"browser": "Edge",
"version": "87.0.664.75",
"platform": "Microsoft Windows",
"source": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 Edg/87.0.664.75"
},
"__v": 0
}
]
我想做的是,用 analytics 文档中的值填充 links 文档中的 analytics
数组,然后还总结了 os 和 browser 对象中每个字段的 true
布尔值的计数。我正在寻找的输出结构是 -
{
"_id": null,
"visit_count": 20,
"password_protected": false,
"description": null,
"alias": "g",
"short_url": "https://reduced.me/g",
"long_url": "https://google.com",
"created": "2021-01-16T11:49:42.517Z",
"analytics": {
"os": {
"windows": 2,
"linux": 0,
"mac": 0,
"android": 0
},
"browser": {
"opera": 0,
"ie": 0,
"edge": 1,
"safari": 0,
"firefox": 1,
"chrome": 0
}
}
}
这里,例如,windows:2
显示在整个文档中 windows
的值为 true
的次数。
目前我是这样做的
const analytics = await LinkModel.aggregate([
{ $match: { short_url: req.body.short_url } },
{
$lookup: {
from: 'analytics',
localField: 'analytics',
foreignField: '_id',
as: 'analytics',
},
},
{ $unwind: '$analytics' },
{
$group: {
_id: null,
visit_count: { $first: '$visit_count' },
password_protected: { $first: '$password_protected' },
description: { $first: '$description' },
alias: { $first: '$alias' },
short_url: { $first: '$short_url' },
long_url: { $first: '$long_url' },
created: { $first: '$created' },
windows: {
$sum: { $cond: ['$analytics.os.windows', 1, 0] },
},
linux: {
$sum: { $cond: ['$analytics.os.linux', 1, 0] },
},
mac: {
$sum: { $cond: ['$analytics.os.mac', 1, 0] },
},
android: {
$sum: { $cond: ['$analytics.os.android', 1, 0] },
},
opera: {
$sum: { $cond: ['$analytics.browser.opera', 1, 0] },
},
ie: {
$sum: { $cond: ['$analytics.browser.ie', 1, 0] },
},
edge: {
$sum: { $cond: ['$analytics.browser.edge', 1, 0] },
},
safari: {
$sum: {
$cond: ['$analytics.browser.safari', 1, 0],
},
},
firefox: {
$sum: {
$cond: ['$analytics.browser.firefox', 1, 0],
},
},
chrome: {
$sum: {
$cond: ['$analytics.browser.chrome', 1, 0],
},
},
},
},
])
这确实给出了这样的输出
[{
"_id": null,
"visit_count": 20,
"password_protected": false,
"description": null,
"alias": "g",
"short_url": "https://reduced.me/g",
"long_url": "https://google.com",
"created": "2021-01-16T11:49:42.517Z",
"windows": 2,
"linux": 0,
"mac": 0,
"android": 0,
"opera": 0,
"ie": 0,
"edge": 1,
"safari": 0,
"firefox": 1,
"chrome": 0
}]
它有我需要的所有数据,但结构不正确。我使用 mongoose 作为 ORM。任何帮助,将不胜感激。谢谢。
你可以使用$addFields
得到你想要的输出
db.collection.aggregate([
{
$addFields: {
"analytics": {
"os": {
"windows": "$windows",
"linux": "$linux",
"mac": "$mac",
"android": "$android"
},
"browser": {
"opera": "$opera",
"ie": "$ie",
"edge": "$edge",
"safari": "$safari",
"firefox": "$firefox",
"chrome": "$chrome"
}
},
"windows": "$$REMOVE",
"linux": "$$REMOVE",
"mac": "$$REMOVE",
"android": "$$REMOVE",
"opera": "$$REMOVE",
"ie": "$$REMOVE",
"edge": "$$REMOVE",
"safari": "$$REMOVE",
"firefox": "$$REMOVE",
"chrome": "$$REMOVE"
}
}
])
我有两个mongo结构文件
链接文档
{
"_id": {
"$oid": "6002d2d627925c4194a15a94"
},
"visit_count": 20,
"password": null,
"password_protected": false,
"description": null,
"analytics": [
{
"$oid": "6002d568e9c7d24d34413492"
},
{
"$oid": "6002d612464785401824a782"
}
],
"alias": "g",
"short_url": "https://reduced.me/g",
"long_url": "https://google.com",
"created": {
"$date": "2021-01-16T11:49:42.517Z"
},
"__v": 2
}
分析文档
[
{
"_id": {
"$oid": "6002d568e9c7d24d34413492"
},
"os": {
"windows": true,
"linux": false,
"mac": false,
"android": false
},
"browser": {
"opera": false,
"ie": false,
"edge": false,
"safari": false,
"firefox": true,
"chrome": false
},
"details": {
"os": "Windows 10.0",
"browser": "Edge",
"version": "87.0.664.75",
"platform": "Microsoft Windows",
"source": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 Edg/87.0.664.75"
},
"__v": 0
},
{
"_id": {
"$oid": "6002d612464785401824a782"
},
"os": {
"windows": true,
"linux": false,
"mac": false,
"android": false
},
"browser": {
"opera": false,
"ie": false,
"edge": true,
"safari": false,
"firefox": false,
"chrome": false
},
"details": {
"os": "Windows 10.0",
"browser": "Edge",
"version": "87.0.664.75",
"platform": "Microsoft Windows",
"source": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 Edg/87.0.664.75"
},
"__v": 0
}
]
我想做的是,用 analytics 文档中的值填充 links 文档中的 analytics
数组,然后还总结了 os 和 browser 对象中每个字段的 true
布尔值的计数。我正在寻找的输出结构是 -
{
"_id": null,
"visit_count": 20,
"password_protected": false,
"description": null,
"alias": "g",
"short_url": "https://reduced.me/g",
"long_url": "https://google.com",
"created": "2021-01-16T11:49:42.517Z",
"analytics": {
"os": {
"windows": 2,
"linux": 0,
"mac": 0,
"android": 0
},
"browser": {
"opera": 0,
"ie": 0,
"edge": 1,
"safari": 0,
"firefox": 1,
"chrome": 0
}
}
}
这里,例如,windows:2
显示在整个文档中 windows
的值为 true
的次数。
目前我是这样做的
const analytics = await LinkModel.aggregate([
{ $match: { short_url: req.body.short_url } },
{
$lookup: {
from: 'analytics',
localField: 'analytics',
foreignField: '_id',
as: 'analytics',
},
},
{ $unwind: '$analytics' },
{
$group: {
_id: null,
visit_count: { $first: '$visit_count' },
password_protected: { $first: '$password_protected' },
description: { $first: '$description' },
alias: { $first: '$alias' },
short_url: { $first: '$short_url' },
long_url: { $first: '$long_url' },
created: { $first: '$created' },
windows: {
$sum: { $cond: ['$analytics.os.windows', 1, 0] },
},
linux: {
$sum: { $cond: ['$analytics.os.linux', 1, 0] },
},
mac: {
$sum: { $cond: ['$analytics.os.mac', 1, 0] },
},
android: {
$sum: { $cond: ['$analytics.os.android', 1, 0] },
},
opera: {
$sum: { $cond: ['$analytics.browser.opera', 1, 0] },
},
ie: {
$sum: { $cond: ['$analytics.browser.ie', 1, 0] },
},
edge: {
$sum: { $cond: ['$analytics.browser.edge', 1, 0] },
},
safari: {
$sum: {
$cond: ['$analytics.browser.safari', 1, 0],
},
},
firefox: {
$sum: {
$cond: ['$analytics.browser.firefox', 1, 0],
},
},
chrome: {
$sum: {
$cond: ['$analytics.browser.chrome', 1, 0],
},
},
},
},
])
这确实给出了这样的输出
[{
"_id": null,
"visit_count": 20,
"password_protected": false,
"description": null,
"alias": "g",
"short_url": "https://reduced.me/g",
"long_url": "https://google.com",
"created": "2021-01-16T11:49:42.517Z",
"windows": 2,
"linux": 0,
"mac": 0,
"android": 0,
"opera": 0,
"ie": 0,
"edge": 1,
"safari": 0,
"firefox": 1,
"chrome": 0
}]
它有我需要的所有数据,但结构不正确。我使用 mongoose 作为 ORM。任何帮助,将不胜感激。谢谢。
你可以使用$addFields
得到你想要的输出
db.collection.aggregate([
{
$addFields: {
"analytics": {
"os": {
"windows": "$windows",
"linux": "$linux",
"mac": "$mac",
"android": "$android"
},
"browser": {
"opera": "$opera",
"ie": "$ie",
"edge": "$edge",
"safari": "$safari",
"firefox": "$firefox",
"chrome": "$chrome"
}
},
"windows": "$$REMOVE",
"linux": "$$REMOVE",
"mac": "$$REMOVE",
"android": "$$REMOVE",
"opera": "$$REMOVE",
"ie": "$$REMOVE",
"edge": "$$REMOVE",
"safari": "$$REMOVE",
"firefox": "$$REMOVE",
"chrome": "$$REMOVE"
}
}
])