Google Cloud Datastore 中我需要什么索引来根据 ID 和另一个 属性 进行过滤?

What index do I need in Google Cloud Datastore to filter based on ID and another property?

我使用 Google Cloud Datastore 来存储具有 Datastore 生成的 ID 作为主键的实体。 此外,我还为每个实体存储了其他属性,在本例中为 owner.

Google 云数据存储控制台中的一个实体如下所示:

|Name/ID             |owner           |...|
|id=5657437197565952 |5634472569470976|...|

然后我想根据 key (id) 和 属性 owner.

过滤实体

为此,我知道我需要一个复合索引才能同时过滤字段 (id) 和所有者。所以我使用以下 index.yaml 文件创建了一个复合索引:

indexes:
- kind: job
  ancestor: no
  properties:
  - name: __key__
  - name: owner

# AUTOGENERATED

索引显示在云控制台中,如果我使用云控制台 UI 在两个字段上进行过滤,它会在 table 中过滤正确的实体。我在那里做的过滤器是:

但是,当我尝试使用以下代码 Google 通过 Node.js 库检索此实体时,我没有得到任何结果:

const {Datastore} = require('@google-cloud/datastore');

async function quickStart() {
  const projectId = 'myproject';

  // Creates a client
  const datastore = new Datastore({
    projectId: projectId,
  });

  const keySelector = datastore.key(['myentity', '5657437197565952']);
  const query = datastore.createQuery('myentity').filter('key', keySelector).filter('owner', '=', '5634472569470976');

  const val = await query.run((err, entities, info) => {
    console.log(entities);
  });

  console.log('Got ' + val);
}
quickStart().catch(console.error);

entities 是空的,如果字符串化,val 就是下面的内容:

[[],{"moreResults":"NO_MORE_RESULTS","endCursor":"CgA="}]

我还尝试创建另一个名为 id 而不是 __key__ 的索引,但没有成功。

我现在的问题是:我需要什么复合索引才能对这两个字段执行此筛选,以便 NodeJS 代码也能正确检索实体?

由于您拥有密钥 ID,因此无需再为查询、过滤器和索引操心:最多可以有一个实体匹配此类查询,您可以通过 direct key lookup 获得。我 认为 会是这样的(抱歉,我不 node.js 流利):

const key = datastore.key(['myentity', 5657437197565952]);
const entity = await datastore.get(key);

一个积极的副作用是键查找是高度一致的(查询最终是一致的),请参阅比较 table 在 Eventual Consistency in Cloud Datastore

但是如果您坚持过滤键,那么您必须使用特殊的 __key__ 名称来引用 属性(就像您在索引文件中所做的那样)。来自 Filters

Key filters

To filter on the value of an entity's key, use the special property __key__:

在你的情况下是这样的:

const keySelector = datastore.key(['myentity', 5657437197565952]);
const query = datastore.createQuery('myentity')
                       .filter('__key__', '=', keySelector)
                       .filter('owner', '=', '5634472569470976');

注意keySelector对象创建中的keyid需要不带引号!