MongoDB中如何在一定条件下从数组中获取特定对象
我的MongoDB中有以下数据结构:MongoDB中如何在一定条件下从数组中获取特定对象,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我的MongoDB中有以下数据结构: [ { "_id" : "**************", "primaryKey" : 1, "currentState" : [ { "value" : 5, "status" : "Y" }, { "value" : 5, "status" : "N" } ], "futureState" : { "value"
[
{
"_id" : "**************",
"primaryKey" : 1,
"currentState" : [
{
"value" : 5,
"status" : "Y"
},
{
"value" : 5,
"status" : "N"
}
],
"futureState" : {
"value" : 5,
"status" : "F"
}
},
{
"_id" : "**************",
"primaryKey" : 2,
"currentState" : [
{
"value" : 5,
"status" : "N"
}
],
"futureState" : {}
}
]
我只想获取状态Y为currentState字段的对象,并在另一个文档中获取相应的futureState字段
预期产出:
我不知道如何在MongoDB中获取这些数据,请帮助我。谢谢您可以通过两种方式完成: 聚集 JS
您可以使用以下查询来执行此操作:
db.collection.aggregate([
/** First match is optional for small dataset but highly preferred to filter required docs from huge dataset */
{ $match: { 'currentState.status': 'Y' } },
/** Retain only objects in currentState which has status == 'Y' & add a fake empty object to array */
{ $addFields: { 'currentState': { $concatArrays: [{ $filter: { input: '$currentState', cond: { $eq: ['$$this.status', 'Y'] } } }, [{}]] } } },
/** unwind currentState field across all docs */
{ $unwind: '$currentState' },
/** if currentState is an object for a doc then keep that field & remove futureState else vice-versa */
{
$addFields: {
futureState: { $cond: [{ $ne: ['$currentState', {}] }, '$$REMOVE', '$futureState'] },
currentState: { $cond: [{ $ne: ['$currentState', {}] }, '$currentState', '$$REMOVE'] }
}
}
])
测试:
db.collection.aggregate([
{
$project: {
doc1: {
$filter: {
input: {
$map: {
input: {
$objectToArray: "$$ROOT"
},
as: "root",
in: {
k: "$$root.k",
v: {
$cond: [
{
$eq: [
"$$root.k",
"currentState"
]
},
{
$ifNull: [
{
$arrayElemAt: [
{
$filter: {
input: "$$root.v",
cond: {
$eq: [
"$$this.status",
"Y"
]
}
}
},
0
]
},
{}
]
},
"$$root.v"
]
}
}
}
},
cond: {
$ne: [
"$$this.k",
"futureState"
]
}
}
},
doc2: {
$filter: {
input: {
$objectToArray: "$$ROOT"
},
cond: {
$ne: [
"$$this.k",
"currentState"
]
}
}
}
}
},
{
$project: {
tmp: [
{
$arrayToObject: "$doc1"
},
{
$arrayToObject: "$doc2"
}
]
}
},
{
$unwind: "$tmp"
},
{
$replaceWith: "$tmp"
}
])
db.collection.find({}).forEach(function(doc){
var aux = Object.assign({}, doc);
delete aux.currentState;
doc.currentState = doc.currentState.filter(x => x.status == "Y");
doc.currentState = doc.currentState.length > 0 ? doc.currentState[0] : {};
delete doc.futureState;
print(doc);
print(aux);
})
db.collection.aggregate([
/** First match is optional for small dataset but highly preferred to filter required docs from huge dataset */
{ $match: { 'currentState.status': 'Y' } },
/** Retain only objects in currentState which has status == 'Y' & add a fake empty object to array */
{ $addFields: { 'currentState': { $concatArrays: [{ $filter: { input: '$currentState', cond: { $eq: ['$$this.status', 'Y'] } } }, [{}]] } } },
/** unwind currentState field across all docs */
{ $unwind: '$currentState' },
/** if currentState is an object for a doc then keep that field & remove futureState else vice-versa */
{
$addFields: {
futureState: { $cond: [{ $ne: ['$currentState', {}] }, '$$REMOVE', '$futureState'] },
currentState: { $cond: [{ $ne: ['$currentState', {}] }, '$currentState', '$$REMOVE'] }
}
}
])