这一篇接着记录一下查询相关的操做。想象一下,若是想要在一张表格中展现某些车辆的耗损和营收状况,咱们该怎么处理。车辆、耗损、营收各自存储在一张表中,耗损和营收中冗余了车辆信息……咱们便想到了关联查询。mongodb 3.2+中开始支持关联查询,下面介绍一下写关联查询的过程。html
测试1、mongodb
db.getCollection('FormInstace').aggregate([ { $match: { "FormItems.key": { $ne: null } } }, { $addFields: { FormValueObj: { $arrayToObject: { $map: { input: "$FormItems", as: "field", in: [ "$$field.key", "$$field.value" ] } } } } }, { $replaceRoot: { newRoot: { $mergeObjects: [ "$FormValueObj", "$$ROOT" ] } } }, { $project: { FormItems:0, FormValueObj:0 } }, { $lookup:{ from:"FormInstace", localField:'_id', foreignField:'FormItems.value.id', as:'RelationData' } } ]);
结合前面笔记的成果和官方文档写了第一个关联查询,此次查询跑了300s直接累死了,因而我便介绍了一下数量。数组
测试2、数据结构
db.getCollection('FormInstace').aggregate([ { $match: { "_id":{$in:["1","2","3"]}, "FormItems.key": { $ne: null } } }, { $addFields: { FormValueObj: { $arrayToObject: { $map: { input: "$FormItems", as: "field", in: [ "$$field.key", "$$field.value" ] } } } } }, { $replaceRoot: { newRoot: { $mergeObjects: [ "$FormValueObj", "$$ROOT" ] } } }, { $project: { FormItems:0, FormValueObj:0 } }, { $lookup:{ from:"FormInstace", localField:'_id', foreignField:'FormItems.value.id', as:'RelationData' } } ]);
此次总算没有报错,可是耗时也够长的(十多秒);关联数据(RelationData)确实是查出来了,可是该数组中的关联数据仍是原来的数据结构。那么咱们是否是一样能够将关联数据中的表单项的值也放到最外层,答案是能够的。测试
测试3、spa
db.getCollection('FormInstace').aggregate([ { $match: { "_id":{$in:["1","2","3"]}, "FormItems.key": { $ne: null } } }, { $addFields: { FormValueObj: { $arrayToObject: { $map: { input: "$FormItems", as: "field", in: [ "$$field.key", "$$field.value" ] } } } } }, { $replaceRoot: { newRoot: { $mergeObjects: [ "$FormValueObj", "$$ROOT" ] } } }, { $project: { FormItems:0, FormValueObj:0 } }, { $lookup:{ from:"FormInstace", localField:'_id', foreignField:'FormItems.value.id', as:'RelationData' } }, { $addFields:{ RelationData:{ $map: { input: "$RelationData", as: "tr", in: { $arrayToObject:{ $map: { input:{ $concatArrays: [ [ {key:"_id",value:"$$tr._id"}, {key:"ExtendData",value:"$$tr.ExtendData"}, {key:"CreateUserId",value:"$$tr.CreateUserId"}, {key:"CreateUserName",value:"$$tr.CreateUserName"}, {key:"CreateDate",value:"$$tr.CreateDate"}, {key:"LastModifyDate",value:"$$tr.LastModifyDate"}, {key:"FormId",value:"$$tr.FormId"}, {key:"FormVersion",value:"$$tr.FormVersion"}, ], "$$tr.FormItems" ] }, as: "field", in: ["$$field.key","$$field.value"] } } } } } } } ]);
这个查询获得了咱们想要的效果,可是这个关联查询太费劲了,不单是代码一大推,而且还要处理关联数据(RelationData)的结构……由于全部的数据都放在同一张表中,以前咱们处理过这张表,如今还要处理一遍,不太情愿😔😔😔。以前不是能够建立视图吗?那咱们是否是能够用视图关联视图,赶忙试试。3d
测试四(建立视图)、code
db.getCollection('FormInstaceView').aggregate([ { $match: { "_id":{$in:["1","2","3"]} } }, { $lookup:{ from:"FormInstaceView", localField:'_id', foreignField:'1572493552001.id', as:'RelationData' } } ]);
不知道你有没有发现视图关联查询和上面的关联查询有何不一样以及查询结果的不一样。对比查询结果发现都是主键ID为1的车辆:非视图是163条关联数据,而视图状况下是58条。再看一下查询语句你会发现非视图状况的foreignField为'FormItems.value.id'而视图状况下为'1572493552001.id',根据外键来看,视图明显缩小了范围,这里就三张表而且只有车辆耗损表中有此字段,可是'FormItems.value.id'就不同了,车辆营收表中也表单项的值是这样的结构。也就是说非视图的关联查询查出了全部表中具备相似结构的关联数据,而视图状况下在这里仅查询的是车辆耗损表中的关联数据。虽然如今查询车辆的耗损信息没有问题,可是若是另一个表中也‘1572493552001’这个字段而且结构也是同样的,那么查询仍然存在问题。因此稳妥的办法应该是关联查询的时候首先肯定哪一个表以后才是哪一个字段。orm
测试5、htm
db.getCollection('FormInstace').aggregate([ { $match: { "FormItems.key": { $ne: null } } }, { $addFields: { FormValueObj: { $arrayToObject: { $map: { input: "$FormItems", as: "field", in: [ "$$field.key", "$$field.value" ] } } } } }, { $replaceRoot: { newRoot: { $mergeObjects: [ "$FormValueObj", "$$ROOT" ] } } }, { $project: { FormItems:0, FormValueObj:0 } }, { $match: { "_id": { $in: ["1","2","3"] }, } }, { $lookup:{ from:"FormInstace", let: { tempMainRelationKey1: "$_id" }, pipeline:[ { $match: { FormId: "507048044944692000" } }, { $addFields: { FormValueObj: { $arrayToObject: { $map: { input: "$FormItems", as: "field", in: [ "$$field.key", "$$field.value" ] } } } } }, { $replaceRoot: { newRoot: { $mergeObjects: [ "$FormValueObj", "$$ROOT" ] } } }, { $project: { FormItems:0, FormValueObj:0 } }, { $match: { $expr: { $eq: [ "$1572493552001.id","$$tempMainRelationKey1" ] } } }, ], as:'RelationData' } } ]);
此次查询在关联的时候就肯定了FormId(指定车辆耗损表),以后再用外键等值查询,所以这个查询结果没有问题。和前面笔记中:查询车辆信息表中主键ID为1的车辆的全部耗损记录的结果相同都是58条……
好了就到这里了,谢谢。