使用 Datastore 模式的 Cloud Firestore

Firestore 是一个 NoSQL 文档数据库,能够自动扩缩、具备出色的性能,并且易于进行应用开发。Firestore 是 Datastore 的最新版本;与 Datastore 相比,这个新版本引入了多项改进功能。

对于主要将由 App Engine 应用使用的数据库,我们建议使用 Datastore 模式 的 Firestore。如需详细了解 Firestore 模式,请参阅选择原生模式或 Datastore 模式

本文档介绍了如何使用 Google Cloud 客户端库将数据存储在 Datastore 模式数据库中,以及如何从 Datastore 模式数据库中检索数据。

前提条件和设置

请按照 App Engine Java 版“Hello, World!”中的说明设置您的环境和项目,并了解如何在 App Engine 中设计 Java 应用的结构。记录并保存项目 ID,因为您需要用其来运行本文档中介绍的示例应用。

克隆代码库

下载(克隆)示例:

git clone https://github.com/GoogleCloudPlatform/java-docs-samples
cd java-docs-samples/flexible/datastore

修改项目配置并设置依赖项

pom.xml 中,设置允许您使用 Datastore 模式的依赖项:

<!--  Using libraries-bom to manage versions.
See https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/The-Google-Cloud-Platform-Libraries-BOM -->
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>libraries-bom</artifactId>
      <version>10.1.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-datastore</artifactId>
  </dependency>
</dependencies>

应用代码

示例应用会记录、检索和显示访问者的 IP。您会看到,日志条目是一个类型为 visit 的简单双字段类,系统会使用数据存储区 add() 命令将其保存为 Datastore 模式。然后,使用数据存储区 run() 命令以降序检索最近十条访问记录。

@SuppressWarnings("serial")
@WebServlet(name = "datastore", value = "")
public class DatastoreServlet extends HttpServlet {

  @Override
  public void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws IOException, ServletException {
    // store only the first two octets of a users ip address
    String userIp = req.getRemoteAddr();
    InetAddress address = InetAddress.getByName(userIp);
    if (address instanceof Inet6Address) {
      // nest indexOf calls to find the second occurrence of a character in a string
      // an alternative is to use Apache Commons Lang: StringUtils.ordinalIndexOf()
      userIp = userIp.substring(0, userIp.indexOf(":", userIp.indexOf(":") + 1)) + ":*:*:*:*:*:*";
    } else if (address instanceof Inet4Address) {
      userIp = userIp.substring(0, userIp.indexOf(".", userIp.indexOf(".") + 1)) + ".*.*";
    }

    Datastore datastore = DatastoreOptions.getDefaultInstance().getService();
    KeyFactory keyFactory = datastore.newKeyFactory().setKind("visit");
    IncompleteKey key = keyFactory.setKind("visit").newKey();

    // Record a visit to the datastore, storing the IP and timestamp.
    FullEntity<IncompleteKey> curVisit =
        FullEntity.newBuilder(key).set("user_ip", userIp).set("timestamp", Timestamp.now()).build();
    datastore.add(curVisit);

    // Retrieve the last 10 visits from the datastore, ordered by timestamp.
    Query<Entity> query =
        Query.newEntityQueryBuilder()
            .setKind("visit")
            .setOrderBy(StructuredQuery.OrderBy.desc("timestamp"))
            .setLimit(10)
            .build();
    QueryResults<Entity> results = datastore.run(query);

    resp.setContentType("text/plain");
    PrintWriter out = resp.getWriter();
    out.print("Last 10 visits:\n");
    while (results.hasNext()) {
      Entity entity = results.next();
      out.format(
          "Time: %s Addr: %s\n", entity.getTimestamp("timestamp"), entity.getString("user_ip"));
    }
  }
}

使用 index.yaml 文件

示例应用会执行简单的查询。更为复杂的 Datastore 模式查询需要使用一个或多个索引,您必须在随应用一起上传的 index.yaml 文件中指定这些索引。此文件可以手动创建,也可以在本地测试应用时自动生成。

本地测试

如果您需要在本地开发和测试应用,则可以使用 Datastore 模式模拟器

了解详情

如需全面了解 Datastore 模式(包括优化和概念),请参阅 Datastore 模式 Cloud Firestore 文档