dounianluo0086
2017-03-25 13:16
浏览 73

按给定字段搜索嵌套对象的数组

I have the following structure of the Room object.

type Room struct {
Id          bson.ObjectId       `json:"id" bson:"_id,omitempty"`
Title       string              `json:"title" bson:"title"`
Description string              `json:"description" bson:"description,omitempty"`
Type        string              `json:"type" bson:"type,omitempty"`
AdminId     bson.ObjectId       `json:"admin_id" bson:"admin_id"`
CreatedOn   time.Time           `json:"created_on" bson:"created_on"`
Messages    []Message           `json:"messages" bson:"messages,omitempty"`}

Where Messages is nested array of objects that has the following structure

type Message struct {
Id      bson.ObjectId   `json:"id" bson:"_id,omitempty"`
Text        string          `json:"text" bson:"text"`
Author      Author          `json:"author" bson:"author"`
CreatedOn   time.Time   `json:"createdon" bson:"created_on"`
Reply       []Message   `json:"reply" bson:"reply,omitempty"`}

I want to perform the search query by the messages in the collection of rooms. I tried using "$in" but I did not help me.

Moreover, I have to search elements by matching values. I can do this using bson regular expressions.

&bson.RegEx{Pattern: textToFind, Options: "i"}

Summing up I need to search messages by the Text field in the nested object in the Room document.

P.S. Sorry for possible mistakes, English is not my native language.

UPDATE

Basically, I want to find all the messages in the given room that contains some substring. For example, search for all messages in the room (chat) 'A' that contains 'some text' substring.

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • duange051858 2017-03-25 15:15
    已采纳

    You can try the below mongo shell aggregation pipeline.

    $matches on some room attribute (ex _id).

    $unwind messages( transform messages array into object ) in the room.

    $matches on input regex against text field to filter messages.

    $groups the message objects back into messages array.

    $project to exclude _id and include only messages for output.

    db.collection.aggregate(
    {$match:{"_id":roomid}}, 
    {$unwind:"$messages"}, 
    {$match:{"messages.text": { $regex: /textToFind/i } }},
    {$group:{_id:null,messages:{$push:"$messages"}}}, 
    {$project:{_id:0, messages:1}})
    

    Below is untested mgo equivalent.

    match1 := bson.M{
        "$match": bson.M{
            "_id": roomid,
        },
    }
    
    unwind := bson.M{
        "$unwind": "$messages",
    }
    
    match2 := bson.M{
        "$match": bson.M{"messages.text": &bson.RegEx{Pattern: textToFind, Options: "i"}},
    }
    
    group := bson.M{
        "$group": bson.M{
            "_id": null,
            "messages": bson.M{
                "$push": "$messages",
            },
        },
    }
    
    project := bson.M{
        "$project":  bson.M{
            "_id": 0, 
            "messages":1,
        },
    }
    
    all := []bson.M{match1, unwind, match2, group, project}
    pipe := collection.Pipe(all)
    
    result := []bson.M{}
    err := pipe.All(&result)
    
    点赞 评论

相关推荐 更多相似问题