我有一个非常复杂的查询,我需要为我的项目,似乎找不到它的工作实现。下面的函数可以工作,但是现在我需要添加一个$lookup
语句来填充profile对象。如您所见,每个匹配都有一个PartnerA
和partnerB
类型的Partner
。每个Partner
都有一个LiteOffer
女巫有一个配置文件。需要从配置文件集合中添加配置文件,使用PartnerA.ID
和PartnerB.ID
作为查找的localFields。
基本上,问题是:我在函数中接收到一个Partner.ID,它也是profile
集合中配置文件的id。然后,我需要从matches
集合中筛选出在PartnerA或PartnerB中具有相同Partner.ID的所有Partner.ID(只有一个合作伙伴具有相同的ID,而另一个则有不同的ID)。最后,我必须使用mongo $lookup
来使用相应的PartnerA.Offer.Profile和PartnerB.Offer.Profile检索配置文件。
下面是匹配结构(我删除了许多字段,以便更容易阅读):
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)
return nil, err
}
matches = append(matches, m)
}
return &matches, nil
}
发布于 2022-03-08 07:37:31
带有查找的聚合查询(运行在mongosh
或mongo
shell中):
var ID = 'some_value' // to match with the partner A and B ids
var pipeline = [
// Initial filter on the 'match' collection
{
$match: {
unlocked: false,
deletedAt: null,
$or: [
{ $and: [ { 'partnerA.id': ID }, { 'partnerA.looksInteresting': false } ] },
{ $and: [ { 'partnerB.id': ID }, { 'partnerA.looksInteresting': false } ] },
]
} },
// Lookup 'profile' collection and get the matching details for the corresponding partner A and B (of 'match')
{
$lookup: {
from: 'profile',
let: { pa_id: '$partnerA.id', pb_id: '$partnerB.id' },
as: 'matched_partner_profiles',
pipeline: [
{
$match: {
$expr: {
$or: [
{ $eq: [ '$$pa_id', '$_id' ] },
{ $eq: [ '$$pb_id', '$_id' ] },
]
}
}},
]
}},
]
// Run the aggregation query, using the pipeline defined above
db.getCollection('match').aggregate(pipeline)
https://stackoverflow.com/questions/71387340
复制相似问题