祖先查询直接后代 - Google 数据存储
Ancestor Query Direct Descendants - Google Datastore
我正在 Google App Engine 中构建目录应用程序,使用 Go 和 Google 数据存储。我正在使用数据存储的 Ancestor
功能来管理不同的产品类别。这是一些数据的示例:
Musical Instruments -> Guitars -> Gibson -> Les Paul
Musical Instruments -> Guitars -> Fender -> Stratocaster
Musical Instruments -> Bass Guitars -> Music Man -> Stingray
乐器是根实体。当我单击它时,我希望看到 Guitars
和 Bass Guitars
,但我看到的是 Musical Instruments
的所有后代,一直到最后一个实体。这不是我要找的。目前我只对乐器的直系后代感兴趣。
一些帖子 like this one 建议在数据存储中创建一个字段来跟踪直接 parent。但是,如果我要手动跟踪 parent 实体,为什么还要使用 Ancestor
功能?它会比过滤匹配直接 parent 字段的查询更快吗?
获取类别的方法如下:
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 个交叉-group transaction), 但是你这样使用祖先给我敲响了警钟
通过将实体组视为逻辑结构数据模型的一种方式,很容易被实体组抓住(我有!),但这可能会导致问题,最终导致写入争用不必要的大实体组。
相反,最好考虑应用程序中需要强一致性的点,并围绕这些点设计实体组。
在这种情况下,我可能只有一个 parentCategory
属性(datastore.Key
类型)。然后,您可以像这样查询 Musical Instruments 的子类别:
k := datastore.NewKey(c, "Category", "Musical Instruments", 0, nil)
q := datastore.NewQuery("Category").Filter("parentCategory =", k)
(我是 Go 的新手,所以以上可能是一个近似值)
假设在每个类别中您有某种 Product
并且您想要查询树中任何级别的给定 Category
中的所有 Product
(例如,Telecaster 在 Guitars 或 Minimoog 在 Musical Instruments 那么你可能需要一个多值 属性(在 Go 中,我猜这可能是一个 []datastore.Key
切片)代表类别树的分支。
我正在 Google App Engine 中构建目录应用程序,使用 Go 和 Google 数据存储。我正在使用数据存储的 Ancestor
功能来管理不同的产品类别。这是一些数据的示例:
Musical Instruments -> Guitars -> Gibson -> Les Paul
Musical Instruments -> Guitars -> Fender -> Stratocaster
Musical Instruments -> Bass Guitars -> Music Man -> Stingray
乐器是根实体。当我单击它时,我希望看到 Guitars
和 Bass Guitars
,但我看到的是 Musical Instruments
的所有后代,一直到最后一个实体。这不是我要找的。目前我只对乐器的直系后代感兴趣。
一些帖子 like this one 建议在数据存储中创建一个字段来跟踪直接 parent。但是,如果我要手动跟踪 parent 实体,为什么还要使用 Ancestor
功能?它会比过滤匹配直接 parent 字段的查询更快吗?
获取类别的方法如下:
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 个交叉-group transaction), 但是你这样使用祖先给我敲响了警钟
通过将实体组视为逻辑结构数据模型的一种方式,很容易被实体组抓住(我有!),但这可能会导致问题,最终导致写入争用不必要的大实体组。
相反,最好考虑应用程序中需要强一致性的点,并围绕这些点设计实体组。
在这种情况下,我可能只有一个 parentCategory
属性(datastore.Key
类型)。然后,您可以像这样查询 Musical Instruments 的子类别:
k := datastore.NewKey(c, "Category", "Musical Instruments", 0, nil)
q := datastore.NewQuery("Category").Filter("parentCategory =", k)
(我是 Go 的新手,所以以上可能是一个近似值)
假设在每个类别中您有某种 Product
并且您想要查询树中任何级别的给定 Category
中的所有 Product
(例如,Telecaster 在 Guitars 或 Minimoog 在 Musical Instruments 那么你可能需要一个多值 属性(在 Go 中,我猜这可能是一个 []datastore.Key
切片)代表类别树的分支。