英文:
Google App Engine - Difference between local Dev server and deployed server
问题
我正在Google App Engine上编写一个应用程序,并且已经能够编写在本地运行并将数据放入本地数据存储的代码。然而,当我将代码部署到Google服务器时,没有数据放入数据存储中。我判断没有数据放入数据存储的主要指标是:一是当我进入开发者控制台时,告诉我没有条目;二是当我运行获取数据的页面时,没有返回任何内容。
在生产数据存储中工作之前,我需要在app.yaml或开发者控制台中定义新的Kinds吗?
这是我从数据存储中获取和存储数据的方法。再次强调,在测试环境中可以正常工作,在生产环境中无法工作,编译一切都很顺利。
package tweetdata
import (
"net/url"
"time"
"golang.org/x/net/context"
"google.golang.org/appengine/datastore"
"google.golang.org/appengine/log"
"github.com/ChimeraCoder/anaconda"
)
const linkTweetKind string = "LinkTweet"
const tweetKey string = "Tweets"
const tweetKeyID string = "default_tweetstore"
//LinkTweet包含从推文中提取的地址和原始推文
type LinkTweet struct {
Address *url.URL
Tweet anaconda.Tweet
}
//StoreTweet是用于在数据存储中存储推文的结构体
type StoreTweet struct {
Address string
Text string
TweetID int64
CreatedTime time.Time
Retweets int
Favorites int
}
//TweetScore是一个结构体,根据地址的流行程度显示其相对得分
type TweetScore struct {
Address *url.URL
score int
lastActive time.Time
}
//WriteLinkTweet将给定的推文写入数据存储
func WriteLinkTweet(tweet LinkTweet, c context.Context) error {
log.Infof(c, "Putting Tweet into datastore: %v", tweet.Tweet.Id)
key := datastore.NewIncompleteKey(c, linkTweetKind, getTweetKey(c))
created, _ := tweet.Tweet.CreatedAtTime()
store := &StoreTweet{
Address: tweet.Address.String(),
Text: tweet.Tweet.Text,
TweetID: tweet.Tweet.Id,
CreatedTime: created,
Retweets: tweet.Tweet.RetweetCount,
Favorites: tweet.Tweet.FavoriteCount,
}
err := datastore.RunInTransaction(c, func(c context.Context) error {
_, err := datastore.Put(c, key, store)
log.Errorf(c, "Failed to write LinkTweet to datastore. %v", err.Error())
return err
}, nil)
return err
}
//GetAllNewTweets查询数据存储并获取自给定时间以来创建的所有推文
func GetAllNewTweets(since time.Time, c context.Context) []StoreTweet {
q := datastore.NewQuery(linkTweetKind).Ancestor(getTweetKey(c)).Filter("CreatedTime >=", since)
out := make([]StoreTweet, 0, 15)
q.GetAll(c, &out)
return out
}
//guestbookKey返回用于所有guestbook条目的键。
func getTweetKey(c context.Context) *datastore.Key {
//这里的字符串"default_guestbook"可以变化以拥有多个guestbook。
return datastore.NewKey(c, tweetKey, tweetKeyID, 0, nil)
}
以上是你提供的代码的翻译。
英文:
I'm writing an app on the Google App Engine, and I have been able to write code that runs locally and puts data into the local datastore. However, when I deploy the code to the google server, no data is put into the datastore. My primary indicators that nothing is getting put into the datastore are, one, when I go to the Developer Console, I'm told there are no entries, and two, when I run the page that gets data, nothing is returned.
Do I need to define new Kinds in the app.yaml or developer console before they will work on the production datastore?
Here is my put and get methods from the data store. Again, works in the testing environment and does not work in production, everything compiles just fine.
package tweetdata
import (
"net/url"
"time"
"golang.org/x/net/context"
"google.golang.org/appengine/datastore"
"google.golang.org/appengine/log"
"github.com/ChimeraCoder/anaconda"
)
const linkTweetKind string = "LinkTweet"
const tweetKey string = "Tweets"
const tweetKeyID string = "default_tweetstore"
//LinkTweet contains the address extracted from a tweet and the original tweet
type LinkTweet struct {
Address *url.URL
Tweet anaconda.Tweet
}
//StoreTweet is a struct used for storing a tweet in the datastore
type StoreTweet struct {
Address string
Text string
TweetID int64
CreatedTime time.Time
Retweets int
Favorites int
}
//TweetScore is a struct that shows the relative score of an address based on
// it's populatrity
type TweetScore struct {
Address *url.URL
score int
lastActive time.Time
}
//WriteLinkTweet writes a given Tweet to the datastore
func WriteLinkTweet(tweet LinkTweet, c context.Context) error {
log.Infof(c, "Putting Tweet into datastore: %v", tweet.Tweet.Id)
key := datastore.NewIncompleteKey(c, linkTweetKind, getTweetKey(c))
created, _ := tweet.Tweet.CreatedAtTime()
store := &StoreTweet{Address: tweet.Address.String(),
Text: tweet.Tweet.Text,
TweetID: tweet.Tweet.Id,
CreatedTime: created,
Retweets: tweet.Tweet.RetweetCount,
Favorites: tweet.Tweet.FavoriteCount,
}
err := datastore.RunInTransaction(c, func(c context.Context) error {
_, err := datastore.Put(c, key, store)
log.Errorf(c, "Failed to write LinkTweet to datastore. %v", err.Error())
return err
}, nil)
return err
}
//GetAllNewTweets queries the datastore and gets all tweets created since the last
// time given
func GetAllNewTweets(since time.Time, c context.Context) []StoreTweet {
q := datastore.NewQuery(linkTweetKind).Ancestor(getTweetKey(c)).Filter("CreatedTime >=", since)
out := make([]StoreTweet, 0, 15)
q.GetAll(c, &out)
return out
}
// guestbookKey returns the key used for all guestbook entries.
func getTweetKey(c context.Context) *datastore.Key {
// The string "default_guestbook" here could be varied to have multiple guestbooks.
return datastore.NewKey(c, tweetKey, tweetKeyID, 0, nil)
}
答案1
得分: 2
你正在看到“最终一致性”(通常在初始阶段会令人困惑)的效果。在事务之外写入的实体需要一段时间才能在查询中可见。
https://cloud.google.com/datastore/docs/articles/balancing-strong-and-eventual-consistency-with-google-cloud-datastore/ 解释了这个问题。https://cloud.google.com/appengine/docs/go/datastore/transactions 是针对Go语言的具体说明。
英文:
You're seeing the (often initially confusing) effect of "eventual consistency". Entities that are written outside of a transaction take a while to be visible to queries.
https://cloud.google.com/datastore/docs/articles/balancing-strong-and-eventual-consistency-with-google-cloud-datastore/ explains the problem. https://cloud.google.com/appengine/docs/go/datastore/transactions is specific to go.
答案2
得分: 0
你是否在StoreTweet
结构体的任何字段上使用了datastore:,noindex
?为了对任何字段运行查询,数据存储必须首先对你将要查询的字段进行索引。因此,如果不对这些字段进行索引,查询将返回空值而没有任何错误。你的开发服务器在第一次运行查询后是否会自动在项目中创建一个index.yaml文件?生产数据存储使用该文件来决定哪些字段应该被索引,所有未被索引的字段将无法进行查询。根据你提供的信息,这是我能想到的可能导致查询返回空值的原因。
为了进一步调试此问题,我建议浏览你的生产数据存储,确保你的数据结构正确,并且值设置为你所期望的值。
英文:
Are you using datastore:,noindex
on any fields in the StoreTweet
struct? In order to run any query against any fields, the datastore must first index the fields you'll be querying. So not indexing those fields will cause the query to return nil without any errors. Does your dev server automatically create an index.yaml file in your project after running your queries for the first time? The production datastore uses this file to decide which fields should be indexed, all fields not indexed won't be able to be queried. From the information you've provided, this is all I can think of that would be causing your queries to return empty.
In order to debug this further, I would browse your production datastore and make sure your data is structured properly and the values are set to what you are expecting them to be.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论