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

huangapple go评论72阅读模式
英文:

Search array of nested objects by given field

问题

我有以下的Room对象结构。

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"`
}

其中Messages是一个嵌套的对象数组,具有以下结构。

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"`
}

我想通过房间集合中的消息执行搜索查询。我尝试使用$in,但没有帮助我。

此外,我需要通过匹配值来搜索元素。我可以使用bson正则表达式来实现这一点。

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

总结一下,我需要通过Room文档中嵌套对象的Text字段来搜索消息。

P.S. 对于可能的错误,我表示抱歉,英语不是我的母语。

更新

基本上,我想要找到给定房间中包含某个子字符串的所有消息。例如,在房间(聊天)'A'中搜索包含'some text'子字符串的所有消息。

英文:

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

得分: 1

你可以尝试以下的Mongo Shell聚合管道:

使用$match匹配某个房间属性(例如_id)。

使用$unwind将消息(将messages数组转换为对象)展开。

使用$match根据输入的正则表达式对text字段进行匹配,以过滤messages

使用$group将消息对象重新组合成messages数组。

使用$project排除_id字段,只包含messages作为输出。

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 } }
])

以下是未经测试的mgo等效代码:

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)

希望对你有帮助!

英文:

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)

huangapple
  • 本文由 发表于 2017年3月25日 21:16:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/43016813.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定