在ObjectId字段上的两个集合之间进行$ lookup查询

时间:2018-05-16 10:45:35

标签: mongodb go mongodb-query mgo

我正在Go 1.9.2使用mongoDB 3.4处理api我正在使用mgo作为驱动程序。

在将请求及其结果插入具有两个集合的同一数据库之后,我必须执行一个端点来获取请求的结果。

有两个集合:

第一次收集:requests

第二次收集:results

requests集合的格式为

{ "_id":ObjectId("5afc034f53c9a77a598c8345")
  "  time ":"2018-05-16 10:08:35.024352907 +0000 UTC m=+23.407317980"
  "param_request":[name:"mike",age:"30",job:"Doctor"]
}

results集合的格式为id_request字段是请求文档的_id字段(作为SQL中的外键哲学)

{"_id":ObjectId("5afc035b53c9a77a598c8346")
 "id_request":ObjectId("5afc034f53c9a77a598c8345")
 "name":"Mike"
 "age":"30"
 "job":"Doctor"
 "city":"Tokyo"} 

{"_id":ObjectId("5afc035b53c9a77a598c8347")
 "id_request":ObjectId("5afc034f53c9a77a598c8345")
 "name":"Mike"
 "age":"30"
 "job":"Doctor"
 "city":"London"}


 {"_id":ObjectId("5afc035b53c9a77a598c8349")
 "id_request":ObjectId("5afc034f53c9a77a598c8345")
 "name":"Mike"
 "age":"30"
 "job":"Doctor"
 "city":"Berlin"
 } 

我尝试查询,然后从文档$lookup Documentation

中找到了查找

想要的结果:

 {
 "name":"Mike"
 "age":"30"
 "job":"Doctor"
 "city":"Berlin"

 }

 {
 "name":"Mike"
 "age":"30"
 "job":"Doctor"
 "city":"London"

 }

 {
 "name":"Mike"
 "age":"30"
 "job":"Doctor"
 "city":"Tokyo"

}

这是我做的:

 db.results.aggregate([

  {$lookup: {from:requests, localField: "id_request",foreignField:"_id",as:”results”}},
  {$match:
         { 
      "id_request": ObjectId("5afc034f53c9a77a598c8345") }}]);

这是错误获取:

2018-05-16T11:31:51.261+0000 E QUERY [thread1] SyntaxError: missing } after property list @(shell):1:131

以下是我将SQL哲学作为查询得到的内容:

  select results .* from results join requests on 

  (results.request_id=requests._id 

               and 

    request_id='ObjectId("5afc034f53c9a77a598c8345")');

2 个答案:

答案 0 :(得分:0)

您的问题中的查询有多个问题,可能会导致解析错误。查找阶段中的from属性必须是字符串。此外,您用于as属性()的引号字符不是有效的字符串分隔符。

尝试使用单引号或双引号替换from: requests from: "requests"字符。

db.results.aggregate([
   { $lookup: { from: "requests", localField: "id_request", foreignField: "_id", as: "results" } },
   { $match: { "id_request": ObjectId("5afc034f53c9a77a598c8345") } } 
]);

答案 1 :(得分:0)

如果您在管道中添加两个额外的步骤,$ unwind和$ project,您应该得到您想要的结果。我也会在$ lookup之前进行$ match,你也可以只查找你需要的数据。

我也喜欢通过定义单独的查询并将它们组合在管道调用中来使您的管道查询易于阅读。你问这个问题是一个Go问题,所以Go的做法是:

match := bson.M{"$match": bson.M{"id_request": bson.ObjectIdHex("5afc034f53c9a77a598c8345")}}
lookup := bson.M{"$lookup": bson.M{"from": "requests", "localField": "id_request", "foreignField": "_id", "as": "results"}}
unwind := bson.M{"$unwind": "$results"}
project := bson.M{"$project": bson.M{"_id": 0, "name": 1, "job": 1, "age": 1, "city": 1}}

iter := theCollection.Pipe([]bson.M{match, lookup, unwind, project}).Iter()
answer := bson.M{}
for iter.Next(&answer) {
    fmt.Println(answer)
}
iter.Close()