Quest
Quest

Reputation: 580

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

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?

Upvotes: 0

Views: 880

Answers (2)

user1415083
user1415083

Reputation: 197

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

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

Upvotes: 1

CrazyCrow
CrazyCrow

Reputation: 4235

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 (
    "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:[email protected]:55855/catalog")

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

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

    /*
        // Fill collection with test data (test collection aready has 15 elements)
        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)
    }
}

Upvotes: 2

Related Questions