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

时间:2015-10-07 19:33:15

标签: google-app-engine go google-cloud-datastore

我正在Google App Engine中使用Go和Google Datastore构建目录应用程序。我正在使用数据库的Ancestor功能来管理不同的产品类别。以下是一些数据的示例:

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

Musical Instruments -> Guitars -> Fender -> Stratocaster

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

乐器是根本实体。当我点击它时,我希望看到GuitarsBass Guitars,但我会看到Musical Instruments的所有后代一直到最后一个实体。这不是我想要的。我现在只对乐器的直系后代感兴趣。

有些帖子like this one建议在数据存储区中创建一个字段来跟踪直接父母。但是,如果我要手动跟踪父实体,为什么要使用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

}

1 个答案:

答案 0 :(得分:0)

您需要考虑应用程序中需要强一致性的任何部分,然后考虑哪些实体和&实体组将需要参与相应的查询和交易(您现在可以在跨群组交易中最多使用25个),但是您以这种方式使用祖先会为我敲响警钟。

通过将实体组视为逻辑构建数据模型的一种方式,很容易被实体组抓住(我有!),但这可能会导致问题,最终导致写入争用不必要的大实体组。

相反,最好考虑应用程序中需要强一致性的点,并围绕它设计实体组。

在这种情况下,我可能只有parentCategory属性(类型为datastore.Key)。然后,您可以像这样查询 Musical Instruments 的子类别:

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

(我对Go很新,所以上面的内容可能是近似值)

假设您在每个类别中都有某种Product,并且您希望在树中的任何级别查询给定Product内的所有Category(例如, Guitars 中的Telecaster Musical Instruments 中的 Minimoog 然后您可能需要一个多值属性(在Go中我猜这个可能是[]datastore.Key切片)表示类别树的分支。