祖先查询直接后代-Google数据存储

I'm building a catalog application in Google App Engine, using Go, and Google Datastore. I'm using the Ancestor features of the datatore to manage different product categories. Here's an example of some data:

Musical Instruments -> Guitars -> Gibson -> Les Paul

Musical Instruments -> Guitars -> Fender -> Stratocaster

Musical Instruments -> Bass Guitars -> Music Man -> Stingray

Musical Instruments is the root entity. When I click it, I expect to see Guitars and Bass Guitars, but instead I see everything that is a descendant of Musical Instruments all the way to the last entity. Which is not what I'm looking for. I'm only interested in the direct descendants of Musical instruments at this point.

Some posts, like this one, suggest creating a field in the datastore to track direct parents. But, if I'm going to track parent entities manually, why use the Ancestor features at all? Would it be faster than filtering queries who match a direct parent field?

Here's the method for getting categories:

func (cat *Category) GetCategories(r *http.Request, pk string) ([]CategoryReturn, error) {
//get context
c := appengine.NewContext(r)

var q *datastore.Query
var err error

//get parent key
k, err := datastore.DecodeKey(pk)

if err != nil {
    //handle error
    return []CategoryReturn{}, err
}

q = datastore.NewQuery("Category").Ancestor(k)

//populate category slices
var categories []CategoryReturn
keys, err := q.GetAll(c, &categories)

if err != nil {
    //handle error
    return []CategoryReturn{}, err
}

//create return object
results := make([]CategoryReturn, 0, 20)

for i, r := range categories {
    k := keys[i]
    y := CategoryReturn {
        Name: r.Name,
        Id: k.IntID(),
        Key: k.Encode(),
    }

    results = append(results, y)
}

return results, nil

}

You will need to think about any parts of your application that do need strong consistency and then consider what entities & entity groups will need to participate in the corresponding queries and transactions (you can now have up to 25 in a cross-group transaction), but your use of ancestors in this way rings alarm bells for me.

It's easy to get caught out (I have!) with entity groups by thinking of them as a way to logically structure your data model, but this can cause problems down the line where you end up with write contention on an unnecessarily large entity group.

Instead, it's best to think about the points in your application where you need strong consistency and design your entity groups around that.

In this scenario I would probably just have a parentCategory property (of type datastore.Key). You can then query for subcategories of Musical Instruments like this:

k := datastore.NewKey(c, "Category", "Musical Instruments", 0, nil)
q := datastore.NewQuery("Category").Filter("parentCategory =", k)

(I'm quite new to Go so the above might be an approximation)

Assuming within each category you have some kind of Product and you want to query for all Products within a given Category at any level in the tree (e.g., Telecaster in Guitars, or Minimoog in Musical Instruments then you will probably need a multi-value property (in Go I guess this would probably be a []datastore.Key slice) representing the branch of the Category tree.