我正在使用Go和Google Datastore在Google App Engine中构建目录应用程序。我正在使用Ancestordatatore 的功能来管理不同的产品类别。这是一些数据的示例:
Ancestor
Musical Instruments -> Guitars -> Gibson -> Les Paul
Musical Instruments -> Guitars -> Fender -> Stratocaster
Musical Instruments -> Bass Guitars -> Music Man -> Stingray
乐器是根实体。当我单击它时,我希望看到Guitars和Bass Guitars,但是相反,我看到了Musical Instruments所有到最后一个实体的后代。这不是我想要的。目前,我只对乐器的直接后代感兴趣。
Guitars
Bass Guitars
Musical Instruments
像这样的一些帖子建议在数据存储区中创建一个字段来跟踪直接父母。但是,如果我要手动跟踪父实体,为什么要完全使用这些Ancestor功能?它会比过滤匹配直接父字段的查询更快吗?
这是获取类别的方法:
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 }
您将需要考虑应用程序中确实需要高度一致性的任何部分,然后考虑哪些实体和实体组需要参与相应的查询和事务(现在,跨组事务中最多可以包含25个),但是您以这种方式使用祖先会为我敲响警钟。
通过将实体组视为逻辑上构建数据模型的一种方式,很容易被实体组所吸引(我有!),但这可能会导致问题,最终导致不必要的大型实体组发生写争用。
相反,最好考虑一下应用程序中需要强一致性的点,并围绕这些点设计实体组。
在这种情况下,我可能只有一个parentCategory属性(类型为datastore.Key)。然后,您可以查询 乐器的 子类别,如下所示:
parentCategory
datastore.Key
k := datastore.NewKey(c, "Category", "Musical Instruments", 0, nil) q := datastore.NewQuery("Category").Filter("parentCategory =", k)
(我刚开始使用Go,所以上面的内容可能是一个近似值)
每个类别中假设你有某种形式的Product,你想查询所有Product内给予A S Category在树中在任何级别(例如, 电视广播员 在 吉他 ,或 的Minimoog 的 乐器 ,那么你可能需要一个多值属性(在去吧,我想这可能是一个[]datastore.Key切片),代表了类别树的分支。
Product
Category
[]datastore.Key