这是我数据库中的示例数据:
{'data':
[{'is_active': True, 'printer_name': 'A', 'vid': 14510},
{'is_active': True, 'printer_name': 'Changed A', 'vid': 14511}
]
},
{'data':
[{'is_active': False, 'printer_name': 'B', 'vid': 14512}]
}
此处的vid
字段为version id
。无论何时编辑记录,修改后的数据都会被推送到列表中,因此它的vid比旧版本更高。
现在我要定义一个名为get_all_active_printers
的方法,该方法返回所有is_active :True
这是我的尝试,但是当它不应该返回打印机时返回两台打印机B
def get_all_active_printers():
return printers.find(
{'data.is_active': True}, {"data": {"$slice": -1}, '_id': 0, 'vid': 0})
我的查询有什么问题?
编辑1以回应WanBachtiar的评论
这是使用命令print([c for c in get_all_active_printers()])
[{'data': [{'printer_name': 'Changed A', 'vid': 1451906336.6602068, 'is_active': True, 'user_id': ObjectId('566bbf0d680fdc1ac922be4c')}]}, {'data': [{'printer_name': 'B', 'vid': 1451906343.8941162, 'is_active': False, 'user_id': ObjectId('566bbf0d680fdc1ac922be4c')}]}]
正如您在实际输出中看到的那样 - 打印机is_active
的{{1}}值为False,但B
仍然返回get_all_active_printers
这是我的版本详情:
在Ubuntu 14.04上,如果重要的话。
编辑2
还有另一个问题。该查询返回B
字段,即使在投影中已明确提及vid
。
*编辑3 *
当你说
时,我不确定你的意思"确保{' printer_name':' B'}"
没有其他文件
。是的,第二个数据(在打印机B上)有第二行。这是第一个数据 - 当字段'vid': 0
为is_active
时创建打印机。之后它变为true
。这是数据库的快照:
但我希望过滤最新数据,因为旧数据仅用于保留审计跟踪。
如果我将false
移动到投影中,如下面的代码所示:
'data.is_active': True
我收到以下错误消息:
pymongo.errors.OperationFailure:数据库错误:你当前不能 混合包括和排除字段。如果这是一个问题,请联系我们。
那么鉴于上面的快照,我如何基于最新数据进行过滤?对不起,如果我的问题早些时候没有说清楚。
答案 0 :(得分:2)
感谢您澄清问题。
因此,您希望查询仅包含is_active: True
的最新元素的文档。
不幸的是,在您的情况下find({'data.is_active': True})
会找到包含data
元素is_active:True
的所有文档,而不仅仅是数组中的最后一个元素。此外,在不知道数组长度的情况下,您无法使用array.i
语法引用数组的最后一个元素。
然而,还有其他方法/替代方案:
/* When updating */
db.printers.update(
/* Filter document for printer B */
{"data.printer_name": 'B'},
/* Push a new document to the front of the array */
{"$push": {
"data": {
$each: [{'is_active': false, 'printer_name': "B", 'vid': 14513 }],
$position: 0
}
}
}
);
/* When querying now you know that the latest one is on index 0 */
db.printers.find(
{"data.0.is_active": true},
{"data": { $slice: 1} }
);
请注意,$ position是MongoDB v2.6中的新功能。
db.printers.aggregate([
{$unwind: '$data' },
{$sort: { 'data.vid' : 1 } },
{$group: {
'_id': { 'printer_name' : '$data.printer_name', id:'$_id' },
'vid': { $max: '$data.vid' },
'is_active' : { $last: '$data.is_active' }
}
},
{$match:{"is_active": true}}
]);
重新考虑文档架构可能对您有所帮助。例如,您可以考虑让它们保持平坦以便于查询,而不是拥有一系列文档。
{'is_active': true, 'printer_name': 'A', 'vid': 14512}
{'is_active': false, 'printer_name': 'B', 'vid': 14513}
有关不同版本跟踪架构设计的更多示例和讨论,请参阅以下博客文章:
也是架构设计的有用参考:Data Modeling Introduction。
查询返回vid字段,即使有明确提及 ' vid':投影中的0。
您可以使用"data.vid": 0
而不是vid:0
隐藏它。
如果我按照以下代码移动' data.is_active':True到投影...我收到以下错误消息。
您必须遵循预测规则。有关预测的更多信息,请参阅projecting fields from query results。
如果您要开始一个新项目,我建议使用MongoDB的最新稳定版本,目前它是v3.2.0。
问候,
万。