我有一个非常复杂的查询,我需要为我的项目,似乎找不到它的工作实现。下面的函数可以工作,但是现在我需要添加一个 $lookup 语句来填充profile对象。如您所见,每个匹配都有一个 PartnerA 和 partnerB 类型的 Partner 。每个 Partner 都有一个 LiteOffer 女巫有一个配置文件。需要从配置文件集合中添加配置文件,使用 PartnerA.ID 和 PartnerB.ID 作为查找的localFields。
$lookup
PartnerA
partnerB
Partner
LiteOffer
PartnerA.ID
PartnerB.ID
基本上,问题是:我在函数中接收到一个Partner.ID,它也是 profile 集合中配置文件的id。然后,我需要从 matches 集合中筛选出在PartnerA或PartnerB中具有相同Partner.ID的所有Partner.ID(只有一个合作伙伴具有相同的ID,而另一个则有不同的ID)。最后,我必须使用mongo $lookup 来使用相应的PartnerA.Offer.Profile和PartnerB.Offer.Profile检索配置文件。
profile
matches
下面是匹配结构(我删除了许多字段,以便更容易阅读):
type Match struct { ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` PartnerA Partner `json:"partnerA" bson:"partnerA"` PartnerB Partner `json:"partnerB" bson:"partnerB"` Unlocked bool `json:"unlocked" bson:"unlocked"` DeletedAt time.Time `json:"deletedAt,omitempty" bson:"deletedAt,omitempty"` type Partner struct { ID primitive.ObjectID `json:"id,omitempty" bson:"id,omitempty"` Offer LiteOffer `json:"offer,omitempty" bson:"offer,omitempty"` LooksInteresting bool `json:"looksInteresting" bson:"looksInteresting"` Unlocked bool `json:"unlocked" bson:"unlocked"` type LiteOffer struct { ID primitive.ObjectID `json:"id,omitempty" bson:"id,omitempty"` Tags []Tag `json:"tags" bson:"tags,omitempty"` Profile Profile `json:"profile,omitempty" bson:"profile,omitempty"` type Profile struct { ID primitive.ObjectID `json:"id,omitempty" bson:"id" diff:"-"` Name string `json:"name,omitempty" bson:"name,omitempty" diff:"-"` Surname string `json:"surname,omitempty" bson:"surname,omitempty" }
这是我的功能:
func getMatchesByProfileId(id primitive.ObjectID) (*[]Match, error) { var matches []Match filter := bson.M{ "$or": []bson.M{ "partnerA.id": id, "partnerA.looksInteresting": false, "partnerB.id": id, "partnerB.looksInteresting": false, "unlocked": false, "deletedAt": nil, ctx, _ := db.GetTimeoutContext() result, err := getMatchCollection().Find(ctx, filter) if err != nil { log.Error("Could not find matches, Error: ", err) return nil, err for result.Next(ctx) { var m Match if err = result.Decode(&m); err != nil { log.Error("Could not decode offer in getMatchesByProfileId", err) return nil, err matches = append(matches, m) return &matches, nil }
下面是我使用的一个可以工作的管道,但现在我需要将这两个查询组合成一个:
pipeline := mongo.Pipeline{ {{"$match", match}}, {{"$lookup", bson.M{ "from": "profile", "localField": "partnerA.id", "foreignField": "_id", "as": "profile", {{"$unwind", "$profile"}}, }
我希望这能解释一切。我花了好几个小时才找到解决办法。任何帮助都将不胜感激。
如果你有任何问题,请随便问。
谢谢!
发布于 2022-03-14 17:26:42
所以我自己解决了这个问题,下面是函数代码:
func getMatchesByProfileId(id primitive.ObjectID) (*[]Match, error) { var matches []Match match := bson.D{ {"unlocked", false}, {"deletedAt", nil}, {"$or", []bson.M{ "partnerA.id": id, "partnerA.looksInteresting": false, "partnerB.id": id, "partnerB.looksInteresting": false, pipeline := mongo.Pipeline{ {{"$match", match}}, {{"$lookup", bson.M{ "from": "profile", "localField": "partnerA.id", "foreignField": "_id", "as": "partnerA.offer.profile", {{"$unwind", "$partnerA.offer.profile"}}, {{"$lookup", bson.M{ "from": "profile", "localField": "partnerB.id", "foreignField": "_id", "as": "partnerB.offer.profile", {{"$unwind", "$partnerB.offer.profile"}}, ctx, _ := db.GetTimeoutContext() cursor, err := getMatchCollection().Aggregate(ctx, pipeline) if err != nil { log.Error("Could not aggregate matches, Error: ", err) return nil, err defer cursor.Close(ctx) for cursor.Next(ctx) { var m Match if err = cursor.Decode(&m); err != nil { log.Error("Could not decode matches in getMatchesByProfileId error: ", err)