假设我有一个产品日志集合,我的产品上所做的所有更改都将记录在此集合中,即:
+------------------------------+
| productId - status - comment |
| 1 0 .... |
| 2 0 .... |
| 1 1 .... |
| 2 1 .... |
| 1 2 .... |
| 3 0 .... |
+------------------------------+
我希望获得状态为1但尚未成为2的所有产品。在SQL中,查询看起来像:
select productId from productLog as PL1
where
status = 1
and productId not in (
select productId from productLog as PL2 where
PL1.productId = PL2.productId and PL2.status = 2
)
group by productId
我正在使用本机PHP MongoDB驱动程序。
答案 0 :(得分:1)
因为子查询连接中的逻辑只是完全相同的键匹配另一个:
db.status.insert([
{ "productId": 1, "status": 0 },
{ "productId": 2, "status": 0 },
{ "productId": 1, "status": 1 },
{ "productId": 2, "status": 1 },
{ "productId": 1, "status": 2 },
{ "productId": 3, "status": 0 }
])
然后使用.aggregate()
:
db.status.aggregate([
{ "$match": {
"status": { "$ne": 2 }
}},
{ "$group": {
"_id": "$productId"
}}
])
或使用map reduce(使用DBRef):
db.status.mapReduce(
function() {
if ( this.productId.$oid == 2 ) {
emit( this.prouctId.$oid, null )
}
},
function(key,values) {
return null;
},
{ "out": { "inline": 1 } }
);
但这里的SQL再次简单如下:
select productId
from productLog
where status <> 2
group by productId
没有多余的连接在完全相同的键值
答案 1 :(得分:0)
上面的此mongo查询不符合相关要求,
mongo查询的结果包括带有productId=1
的文档,
但是有关SQL的结果却没有。因为在示例数据中:存在1条带有status=2
的记录,而该文档的productId
为1。
因此,假设如上所述执行db.productLog.insert
,则可以使用以下代码获取结果:
//First: subquery for filtering records having status=2:
var productsWithStatus2 = db.productLog .find({"status":2}).map(function(rec) { return rec.productId; });
//Second:final query to get productIds which there not exists having status=2 with same productId :
db.productLog.aggregate([ {"$match":{productId:{$nin:productsWithStatus2}}},{"$group": {"_id": "$productId"}}]) ;
//Alternative for Second final query:
//db.productLog.distinct("productId",{productId:{$nin:productsWithStatus2}});
//Alternative for Second final query,get results with product and status detail:
//db.productLog.find({productId:{$nin:productsWithStatus2}});