在使用Golang实现查询时,只有在聚合查询时才会出现查询中的空数据。

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

Blank data in query with aggregation only when querying with golang implementation

问题

我正在为您翻译以下内容:

我正在尝试使用聚合操作获取一个文档数组。聚合操作可以同时匹配一个聊天数组,按时间戳排序,然后按chat_id分组,只选择每个聊天中的最后一条消息。
所以我有一个包含三个chat_id的数组,我想获取具有这些chat_id的最后三条消息。

以下是两个示例:第一个是在控制台中的聚合操作和我得到的响应示例。第二个是golang中的一个变体,但输出中得到的是空对象。

第一个示例:

db.message.aggregate([
    {
        $match: {
            chat_id: {
                $in: ["dtlzoD9fI15q8_YM6eqp", "unps_ZwBZ7mCubC3TsKl"],
            },
        }
    },
    {
        $sort: {
            "created": -1,
        },
    },
    {
        $group: {
            "_id": {"chat_id": "$chat_id"},
            "doc": { "$last": "$$ROOT" }
        }
    }
])

第一个响应:

[
  {
    "_id": {
      "chat_id": "unps_ZwBZ7mCubC3TsKl"
    },
    "doc": {
      "_id": {"$oid": "63ac61d71a11d3b05340c001"},
      "id": "wsBFKoN51q5v4Nnv3A-B",
      "chat_id": "unps_ZwBZ7mCubC3TsKl",
      "body": "Certainty determine at of arranging perceived situation or. Or wholly pretty county in oppose. Favour met itself wanted settle put garret twenty. In astonished apartments resolution so an it. Unsatiable on by contrasted to reasonable companions an. On otherwise no admitting to suspicion furniture it.",
      "created": 1672241623466
    }
  },
  {
    "_id": {
      "chat_id": "dtlzoD9fI15q8_YM6eqp"
    },
    "doc": {
      "_id": {"$oid": "63ac607f141f0526cba7113d"},
      "id": "jhjVxQUzQbPCLebnupS9",
      "chat_id": "dtlzoD9fI15q8_YM6eqp",
      "body": "Certainty determine at of arranging perceived situation or. Or wholly pretty county in oppose. Favour met itself wanted settle put garret twenty. In astonished apartments resolution so an it. Unsatiable on by contrasted to reasonable companions an. On otherwise no admitting to suspicion furniture it.",
      "created": 1672241279354
    }
  }
]

第二个示例(这不是一个工作示例):

type Message struct {
	ID      string `json:"id" bson:"id"`
	ChatID  string `json:"chat_id" bson:"chat_id"`
	Body    string `json:"body" bson:"body"`
	Created int64  `json:"created" bson:"created"`
}

...
ids := []string{"unps_ZwBZ7mCubC3TsKl", "dtlzoD9fI15q8_YM6eqp"}
matchStage := bson.D{{
	Key: "$match", Value: bson.D{{Key: "chat_id", Value: bson.D{{Key: "$in", Value: ids}}}},
}}
sortStage := bson.D{{"$sort", bson.D{{"created", -1}}}}
groupStage := bson.D{{
	Key: "$group", Value: bson.D{
		{
			Key: "_id", Value: bson.D{
				{"chat_id", "$chat_id"},
			},
		},
		{
			Key: "message", Value: bson.D{
				{"$last", "$$ROOT"},
			},
		},
	},
}}

cursor, err := db.Aggregate(context.Background(), mongo.Pipeline{matchStage, groupStage, sortStage})

if err != nil {}

var messages []*Message
err = cursor.All(context.Background(), &messages)
if err != nil {
	fmt.Print("Cursor err: ", err)
	return
}

defer func() {
	err := cursor.Close(context.Background())
	if err != nil {
		return
	}
}()

第二个响应:

MSG: &{   0} // 空数据
MSG: &{   0}

我想从聚合操作中获取的结果是:

[
  {
    "_id": {"$oid": "63ac607f141f0526cba7113d"},
    "id": "jhjVxQUzQbPCLebnupS9",
    "chat_id": "dtlzoD9fI15q8_YM6eqp",
    "body": "Certainty determine at of arranging perceived situation or. Or wholly pretty county in oppose. Favour met itself wanted settle put garret twenty. In astonished apartments resolution so an it. Unsatiable on by contrasted to reasonable companions an. On otherwise no admitting to suspicion furniture it.",
    "created": 1672241279354
  },
  {
    "_id": {"$oid": "63ac61d71a11d3b05340c001"},
    "id": "wsBFKoN51q5v4Nnv3A-B",
    "chat_id": "unps_ZwBZ7mCubC3TsKl",
    "body": "Certainty determine at of arranging perceived situation or. Or wholly pretty county in oppose. Favour met itself wanted settle put garret twenty. In astonished apartments resolution so an it. Unsatiable on by contrasted to reasonable companions an. On otherwise no admitting to suspicion furniture it.",
    "created": 1672241623466
  }
]
英文:

I'm trying to get an array of documents using aggregation. Aggregation to simultaneously match an array of chats, sort by timestamp, and then group by chat_id, selecting only the last message from each.
So I have an array of three chat_id and I want to get the last three messages that have that chat_id.

Below are two examples: The first is the aggregation in the console and an example of the response I get. The second is a variant in golang, but I get empty objects in the output

This is MongoDB playgroud work example

First example

db.message.aggregate([
    {
        $match: {
            chat_id: {
                $in: ["dtlzoD9fI15q8_YM6eqp", "unps_ZwBZ7mCubC3TsKl"],
            },
        }
    },
    {
        $sort: {
            "created": -1,
        },
    },
    {
        $group: {
            "_id": {"chat_id": "$chat_id"},
            "doc": { "$last": "$$ROOT" }
        }
    }
])

First response

[
  {
    "_id": {
      "chat_id": "unps_ZwBZ7mCubC3TsKl"
    },
    "doc": {
      "_id": {"$oid": "63ac61d71a11d3b05340c001"},
      "id": "wsBFKoN51q5v4Nnv3A-B",
      "chat_id": "unps_ZwBZ7mCubC3TsKl",
      "body": "Certainty determine at of arranging perceived situation or. Or wholly pretty county in oppose. Favour met itself wanted settle put garret twenty. In astonished apartments resolution so an it. Unsatiable on by contrasted to reasonable companions an. On otherwise no admitting to suspicion furniture it. ",
      "created": 1672241623466
    }
  },
  {
    "_id": {
      "chat_id": "dtlzoD9fI15q8_YM6eqp"
    },
    "doc": {
      "_id": {"$oid": "63ac607f141f0526cba7113d"},
      "id": "jhjVxQUzQbPCLebnupS9",
      "chat_id": "dtlzoD9fI15q8_YM6eqp",
      "body": "Certainty determine at of arranging perceived situation or. Or wholly pretty county in oppose. Favour met itself wanted settle put garret twenty. In astonished apartments resolution so an it. Unsatiable on by contrasted to reasonable companions an. On otherwise no admitting to suspicion furniture it. ",
      "created": 1672241279354
    }
  }
]

Second example. This isn't work example

type Message struct {
	ID      string `json:"id" bson:"id"`
	ChatID  string `json:"chat_id" bson:"chat_id"`
	Body    string `json:"body" bson:"body"`
	Created int64  `json:"created" bson:"created"`
}

...
ids := []string{"unps_ZwBZ7mCubC3TsKl", "dtlzoD9fI15q8_YM6eqp"}
matchStage := bson.D{{
	Key: "$match", Value: bson.D{{Key: "chat_id", Value: bson.D{{Key: "$in", Value: ids}}}},
}}
sortStage := bson.D{{"$sort", bson.D{{"created", -1}}}}
groupStage := bson.D{{
	Key: "$group", Value: bson.D{
		{
			Key: "_id", Value: bson.D{
				{"chat_id", "$chat_id"},
			},
		},
		{
			Key: "message", Value: bson.D{
				{"$last", "$$ROOT"},
			},
		},
	},
}}

cursor, err := db.Aggregate(context.Background(), mongo.Pipeline{matchStage, groupStage, sortStage})

if err != nil {}

var messages []*Message
err = cursor.All(context.Background(), &messages)
if err != nil {
	fmt.Print("Cursor err: ", err)
	return
}

defer func() {
	err := cursor.Close(context.Background())
	if err != nil {
		return
	}
}()

Second Response

MSG: &{   0} // empty data
MSG: &{   0}

What I want to get out of aggregation

[
  {
    "_id": {"$oid": "63ac607f141f0526cba7113d"},
    "id": "jhjVxQUzQbPCLebnupS9",
    "chat_id": "dtlzoD9fI15q8_YM6eqp",
    "body": "Certainty determine at of arranging perceived situation or. Or wholly pretty county in oppose. Favour met itself wanted settle put garret twenty. In astonished apartments resolution so an it. Unsatiable on by contrasted to reasonable companions an. On otherwise no admitting to suspicion furniture it. ",
    "created": 1672241279354
  },
  {
    "_id": {"$oid": "63ac61d71a11d3b05340c001"},
    "id": "wsBFKoN51q5v4Nnv3A-B",
    "chat_id": "unps_ZwBZ7mCubC3TsKl",
    "body": "Certainty determine at of arranging perceived situation or. Or wholly pretty county in oppose. Favour met itself wanted settle put garret twenty. In astonished apartments resolution so an it. Unsatiable on by contrasted to reasonable companions an. On otherwise no admitting to suspicion furniture it. ",
    "created": 1672241623466
  },
]

答案1

得分: 1

这个问题可能是因为你的消息模式不正确(注意你的 JS 聚合和 go 聚合之间有一个小差异,前者使用 doc,后者使用 message,我将使用 message)。

type MessageInner struct {
    ID      string `json:"id" bson:"id"`
    ChatID  string `json:"chat_id" bson:"chat_id"`
    Body    string `json:"body" bson:"body"`
    Created int64  `json:"created" bson:"created"`
}

type Message struct {
    MessageInner MessageInner `json:"message" bson:"message"`
}

另一种方法是在最后使用 $replaceRoot 聚合阶段。

{ $replaceRoot: { newRoot: "$message" } }
英文:

This issue is probably because your message schema isn't correct (note there is a small difference between your JS aggregate and your go one in that use use doc in the former and message in the latter, I'll stick with message

type MessageInner struct {
ID      string `json:"id" bson:"id"`
ChatID  string `json:"chat_id" bson:"chat_id"`
Body    string `json:"body" bson:"body"`
Created int64  `json:"created" bson:"created"`
}
type Message struct {
MessageInner Doc `json:"message" bson:"message"`
}

An alternate would be to use the $replaceRoot aggregation stage at the end

{ $replaceRoot: { newRoot: "$message" } }

huangapple
  • 本文由 发表于 2022年12月29日 23:17:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/74952891.html
匿名

发表评论

匿名网友

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

确定