sort a mongodb query based on a field in a subdocument in Go

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

sort a mongodb query based on a field in a subdocument in Go

问题

假设我有以下结构体:

type Test struct {
  Title  string `bson:"title" json:"title"`
  Update Update `bson:"update" json:"update"`
}

type Update struct {
  Changes    []string  `bson:"change" json:"change"`
  UpdatedAt time.Time `bson:"updatedAt" json:"updatedAt"`
}

假设我想按照 "update.updatedAt" 对查询结果进行排序:

cs.Find(bson.M{title: "some title"}).Sort("-update.updatedAt").Limit(10).All(&results)

这个查询不像预期的那样工作。我似乎找不到任何关于如何按子文档字段对查询进行排序的文档。直觉上,我确信我的示例会起作用。作为参考,"-updatedAt" 可以正常工作,但由于不必解释的原因,我必须将 Update 保持为 Test 的子文档。

到目前为止,我看到的每个示例和 Stack Overflow 的问题都涉及对子文档或数组进行排序和重新排序。在这种情况下,我不关心子文档的顺序,也不按数组内的任何内容排序。我只是想按子文档的日期对文档进行排序。

在 Go 的 Mgo Query 库中有没有办法做到这一点?

英文:

suppose I have the following struct

type Test struct {
  Title  string `bson:"title" json:"title"`
  Update Update `bson:"update" json:"update"`
}

type Update struct {
  Changes    []string  `bson:"change" json:"change"`
  UpdatedAt time.Time `bson:"updatedAt" json:"updatedAt"`
}

And suppose I want to sort my results in the Query by "update.updatedAt"

cs.Find(bson.M{title: "some title"}).Sort("-update.updatedAt").Limit(10).All(&results)

This query does not work as expected. I can't seem to find any documentation about how to sort a Query by a subdocument field. Intuitively, I was certain that my example would work. For reference, "-updatedAt" works just fine, but for reasons that aren't necessary to explain, I have to keep Update as a subdocument of Test.

Every example and Stack Overflow question I have seen so far involves the sorting and reordering of subdocuments, or arrays. In this case I don't care about the order of my subdocuments, and I'm not sorting by anything inside of an array. I merely want to sort my the documents by the date of a subdocument.

Is there a way to do this with the Go Mgo Query library?

答案1

得分: 2

我很确定问题出在你的数据结构上,因为下面的代码按预期工作(你可以在你的电脑上测试):

package main

import (
	"fmt"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"log"
	"time"
)

type Test struct {
	Title  string `bson:"title" json:"title"`
	Update Update `bson:"update" json:"update"`
}

type Update struct {
	Changes   []string  `bson:"change" json:"change"`
	UpdatedAt time.Time `bson:"updatedAt" json:"updatedAt"`
}

func main() {
	session, err := mgo.Dial("mongodb://souser:123456@ds055855.mlab.com:55855/catalog")

	if err != nil {
		panic(err)
	}
	defer session.Close()
	session.SetMode(mgo.Monotonic, true)

	c := session.DB("catalog").C("sortable")

	/*
		// 填充测试数据到集合中(测试集合已经有15个元素)
		for i := 0; i < 15; i++ {
			c.Insert(&Test{
				Title: "Title",
				Update: Update{
					Changes:   []string{fmt.Sprintf("Changes #%d", i)},
					UpdatedAt: time.Now(),
				},
			})
		}
	*/

	var results []Test

	err = c.Find(bson.M{"title": "Title"}).Sort("-update.updatedAt").Limit(10).All(&results)
	if err != nil {
		log.Fatal(err)
	}

	for _, e := range results {
		fmt.Println(e.Update.UpdatedAt)
	}
}

以上是你要翻译的内容。

英文:

I'm pretty sure it is something with your data structures because next code works as expected (you can test it on your PC)

package main

import (
	&quot;fmt&quot;
	&quot;gopkg.in/mgo.v2&quot;
	&quot;gopkg.in/mgo.v2/bson&quot;
	&quot;log&quot;
	&quot;time&quot;
)

type Test struct {
	Title  string `bson:&quot;title&quot; json:&quot;title&quot;`
	Update Update `bson:&quot;update&quot; json:&quot;update&quot;`
}

type Update struct {
	Changes   []string  `bson:&quot;change&quot; json:&quot;change&quot;`
	UpdatedAt time.Time `bson:&quot;updatedAt&quot; json:&quot;updatedAt&quot;`
}

func main() {
	session, err := mgo.Dial(&quot;mongodb://souser:123456@ds055855.mlab.com:55855/catalog&quot;)

	if err != nil {
		panic(err)
	}
	defer session.Close()
	session.SetMode(mgo.Monotonic, true)

	c := session.DB(&quot;catalog&quot;).C(&quot;sortable&quot;)

	/*
		// Fill collection with test data (test collection aready has 15 elements)
		for i := 0; i &lt; 15; i++ {
			c.Insert(&amp;Test{
				Title: &quot;Title&quot;,
				Update: Update{
					Changes:   []string{fmt.Sprintf(&quot;Changes #%d&quot;, i)},
					UpdatedAt: time.Now(),
				},
			})
		}
	*/

	var results []Test

	err = c.Find(bson.M{&quot;title&quot;: &quot;Title&quot;}).Sort(&quot;-update.updatedAt&quot;).Limit(10).All(&amp;results)
	if err != nil {
		log.Fatal(err)
	}

	for _, e := range results {
		fmt.Println(e.Update.UpdatedAt)
	}
}

答案2

得分: 0

你需要以逗号(,)分隔的方式传递子文档字段,例如:

cs.Find(bson.M{title: "some title"}).Sort("update","-updatedAt").Limit(10).All(&results)

英文:

You need to pass subdocument fields comma(,) seperated like:

cs.Find(bson.M{title: "some title"}).Sort("update","-updatedAt").Limit(10).All(&results)

huangapple
  • 本文由 发表于 2016年4月6日 03:45:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/36435683.html
匿名

发表评论

匿名网友

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

确定