0

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.

2
  • You can try something like collection.Find(bson.M{"messages.text": &bson.RegEx{Pattern: textToFind, Options: "i"}}) Commented Mar 25, 2017 at 13:55
  • @Veeram I've tried but it does not work. Commented Mar 25, 2017 at 14:26

1 Answer 1

1

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)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.