mongodb 中具有嵌套数组的多个文档分组
multiple grouping of documents with nested array in mongodb
我有一个文档列表,其中包含这些字段 ID:'int'、类别:'text'、字段:'text',以及项目列表 [{title, value}]
documents= [
{ "id":"1",
"category": "education",
"field": "science",
"items": [
{
"title": "item 1",
"value": "10"
},
{
"title": "item 2",
"value": "102"
},
{
"title": "item 4",
"value": "12"
}
]
},
{ "id":"2",
"category": "education",
"field": "science",
"items": [
{
"title": "item 1",
"value": "4"
},
{
"title": "item 2",
"value": "23"
},
{
"title": "item 4",
"value": "45"
}
]
},
{ "id":"3",
"category": "fitness",
"field": "body",
"items": [
{
"title": "item 1",
"value": "87"
},
{
"title": "item 5",
"value": "45"
},
{
"title": "item =3",
"value": "23"
}
]
},
{ "id":"4",
"category": "education",
"field": "culture",
"items": [
{
"title": "item 1",
"value": "187"
},
{
"title": "item 5",
"value": "145"
},
{
"title": "item 3",
"value": "123"
}
]]
我正在与 mongodb(初学者)合作,我很困惑如何首先按类别对这些文档进行分组,然后按字段,然后按项目的标题将它们的值像列表一样推送到数组中价值观的历史。
期望的结果:
newDocument=[
{ "newid":"1",
"category": "education",
"field": "science",
"items": [
{
"title": "item 1",
"value": ["10","4"]
},
{
"title": "item 2",
"value": ["102","23"]
},
{
"title": "item 4",
"value": ["12", "45"]
}
]
},
{ "newid":"2",
"category": "education",
"field": "culture",
"items": [
{
"title": "item 1",
"value": ["187"]
},
{
"title": "item 5",
"value":["145"]
},
{
"title": "item 3",
"value": ["123"]
}
]
}
{ "newid":"3",
"category": "fitness",
"field": "body",
"items": [
{
"title": "item 1",
"value": ["87"]
},
{
"title": "item 5",
"value":["45"]
},
{
"title": "item 3",
"value": ["23"]
}
]
}
]
可以使用聚合查询,但会影响性能和响应速度,有两种选择,一种使用$unwind
,另一种使用$accumulator
运算符,
使用 $accumulator
:
$group
通过 category
和 field
$accumulator
做自定义 JavaScript 逻辑和合并项目数组,你可以根据你的要求改进和更新
$project
显示必填字段
db.collection.aggregate([
{
$group: {
_id: {
category: "$category",
field: "$field"
},
items: {
$accumulator: {
init: function() { return []; },
accumulate: function(items1, items2) {
return items1.concat(items2);
},
accumulateArgs: ["$items"],
merge: function(items1, items2) {
return items1.concat(items2);
},
finalize: function(state) {
var items = {}, finalItems = [];
state.forEach(function(item) {
if (items[item.title]) {
items[item.title].value.push(item.value);
}
else {
item.value = [item.value];
items[item.title] = item;
}
});
for (var i in items) {
finalItems.push(items[i]);
}
return finalItems;
},
lang: "js"
}
}
}
},
{
$project: {
_id: 0,
category: "$_id.category",
field: "$_id.field",
items: 1
}
}
])
使用 $unwind
:(不推荐)
$unwind
解构items
数组
$group
by category
, field
and item
title 并构造数组 if item values
$group
通过 category
和 field
并用 title
和 value
构造 items
数组
$project
显示必填字段
db.collection.aggregate([
{ $unwind: "$items" },
{
$group: {
_id: {
category: "$category",
field: "$field",
title: "$items.title"
},
value: { $push: "$items.value" }
}
},
{
$group: {
_id: {
category: "$_id.category",
field: "$_id.field"
},
items: {
$push: {
title: "$_id.title",
value: "$value"
}
}
}
},
{
$project: {
_id: 0,
category: "$_id.category",
field: "$_id.field",
items: 1
}
}
])
我有一个文档列表,其中包含这些字段 ID:'int'、类别:'text'、字段:'text',以及项目列表 [{title, value}]
documents= [
{ "id":"1",
"category": "education",
"field": "science",
"items": [
{
"title": "item 1",
"value": "10"
},
{
"title": "item 2",
"value": "102"
},
{
"title": "item 4",
"value": "12"
}
]
},
{ "id":"2",
"category": "education",
"field": "science",
"items": [
{
"title": "item 1",
"value": "4"
},
{
"title": "item 2",
"value": "23"
},
{
"title": "item 4",
"value": "45"
}
]
},
{ "id":"3",
"category": "fitness",
"field": "body",
"items": [
{
"title": "item 1",
"value": "87"
},
{
"title": "item 5",
"value": "45"
},
{
"title": "item =3",
"value": "23"
}
]
},
{ "id":"4",
"category": "education",
"field": "culture",
"items": [
{
"title": "item 1",
"value": "187"
},
{
"title": "item 5",
"value": "145"
},
{
"title": "item 3",
"value": "123"
}
]]
我正在与 mongodb(初学者)合作,我很困惑如何首先按类别对这些文档进行分组,然后按字段,然后按项目的标题将它们的值像列表一样推送到数组中价值观的历史。 期望的结果:
newDocument=[
{ "newid":"1",
"category": "education",
"field": "science",
"items": [
{
"title": "item 1",
"value": ["10","4"]
},
{
"title": "item 2",
"value": ["102","23"]
},
{
"title": "item 4",
"value": ["12", "45"]
}
]
},
{ "newid":"2",
"category": "education",
"field": "culture",
"items": [
{
"title": "item 1",
"value": ["187"]
},
{
"title": "item 5",
"value":["145"]
},
{
"title": "item 3",
"value": ["123"]
}
]
}
{ "newid":"3",
"category": "fitness",
"field": "body",
"items": [
{
"title": "item 1",
"value": ["87"]
},
{
"title": "item 5",
"value":["45"]
},
{
"title": "item 3",
"value": ["23"]
}
]
}
]
可以使用聚合查询,但会影响性能和响应速度,有两种选择,一种使用$unwind
,另一种使用$accumulator
运算符,
使用 $accumulator
:
$group
通过category
和field
$accumulator
做自定义 JavaScript 逻辑和合并项目数组,你可以根据你的要求改进和更新$project
显示必填字段
db.collection.aggregate([
{
$group: {
_id: {
category: "$category",
field: "$field"
},
items: {
$accumulator: {
init: function() { return []; },
accumulate: function(items1, items2) {
return items1.concat(items2);
},
accumulateArgs: ["$items"],
merge: function(items1, items2) {
return items1.concat(items2);
},
finalize: function(state) {
var items = {}, finalItems = [];
state.forEach(function(item) {
if (items[item.title]) {
items[item.title].value.push(item.value);
}
else {
item.value = [item.value];
items[item.title] = item;
}
});
for (var i in items) {
finalItems.push(items[i]);
}
return finalItems;
},
lang: "js"
}
}
}
},
{
$project: {
_id: 0,
category: "$_id.category",
field: "$_id.field",
items: 1
}
}
])
使用 $unwind
:(不推荐)
$unwind
解构items
数组$group
bycategory
,field
anditem
title 并构造数组 if item values$group
通过category
和field
并用title
和value
构造 $project
显示必填字段
items
数组
db.collection.aggregate([
{ $unwind: "$items" },
{
$group: {
_id: {
category: "$category",
field: "$field",
title: "$items.title"
},
value: { $push: "$items.value" }
}
},
{
$group: {
_id: {
category: "$_id.category",
field: "$_id.field"
},
items: {
$push: {
title: "$_id.title",
value: "$value"
}
}
}
},
{
$project: {
_id: 0,
category: "$_id.category",
field: "$_id.field",
items: 1
}
}
])