在数据存储区中的嵌入式实体中使用excludeFromIndexes的正确方法是什么

时间:2018-02-06 00:42:25

标签: google-cloud-platform google-cloud-datastore

如果数据存储已编入索引,则不允许超过1500字节的属性。所以,如果我有一个对象

{foo : X, bar : Y}

其中Y超过1500个字符我可以禁用单个属性的索引并通过数组存储它,因此:

[
 { name : 'foo', value: 'X'}, 
 { name: 'bar', value: 'Y', excludeFromIndexes: true}
]

但是,如果属性是嵌入式实体(即另一个实体的属性内的实体)的一部分,则此方法不起作用。 我该如何存储这样的东西?

{ foo : X, bar : { baz : Y } }

这不起作用:

[
 { name : 'foo', value: 'X'}, 
 { name: 'bar', value: 
    {
        name: 'baz', 
        value: 'Y', 
        excludeFromIndexes: true
    },
 excludeFromIndexes: true}
]

这就是:

[
 { name : 'foo', value: 'X'}, 
 { name: 'bar', value: {'baz', 'Y' }, excludeFromIndexes: true}
]

更新: 这是一个示例代码段:

const DataStore = require('@google-cloud/datastore');
const datastore = DataStore({projectId});
const foo1 = { name : { forename: 'Dave', surname : 'Tong' }, colour : 'blue'}

const putAndGet = async data => {
  return new Promise(async (resolve, reject) => {
    try {
      const key = await datastore.save({key: datastore.key([Kind]), data: data});
    } catch (err) {
      reject(err);
    }
    const results = [];
    const query = datastore.createQuery(Kind);
    query.runStream()
      .on('error', (error) => {
        reject(new Error(error));
      })
      .on('data', (entity) => {
        results.push(entity);
      })
      .on('end', () => {
        resolve(results);
      });
  });
}

// This will succeed
putAndGet(foo1).then(ret => {
  for (var i = 0; i < ret.length; i++) {
    console.log(ret[i].name.forename + " likes " + ret[i].colour);
  }

  const str = [];
  for (var i = 0; i < 400; i++) str[i] = 'X';

  const foo2 = {name: {forename: str.join('XXX'), surname: 'Tong'}, colour: 'blue'}
  // This will fail
  return putAndGet(foo2);
}).then(ret => {
  for (var i = 0; i < ret.length; i++) {
    console.log(ret[i].name.forename + " likes " + ret[i].colour);
  }
}).catch(err => {
  console.log(err.message);
});

1 个答案:

答案 0 :(得分:1)

经过一些测试,我能够实现您想要的目标。我也编辑了你的问题,为了让这篇文章的未来读者更清楚,因为你引用了另一个属性&#34;的&#34; 属性部分,但这是在数据存储区为EmbeddedEntity,因此我会坚持使用该名称以获得更清晰的解释。

嵌入式实体的子属性可能超过1500字节,但您必须明确排除这些子属性,否则将显示错误。为此,您必须将每个EmbeddedEntity声明为:

{
  "properties": {
    "surname": {
      "stringValue": "A long surname which has more than 1500B",
      "excludeFromIndexes": true
    },
    "forename": {
      "stringValue": "David"
    }
  }
}

但是使用NodeJS以编程方式声明"excludeFromIndexes": true并不是太直截了当。但最后我设法解决了它。关键是save()功能,您可以在其中声明要从索引中排除的属性子属性,例如:

datastore.save({key: entity_key, data: entity_data, excludeFromIndexes: ['prop1', 'prop2.subprop1']});

在这里,我分享了一小段代码(来自您共享的代码段中的MCV),它可以工作并创建一个包含长属性的属性的实体:

const DataStore = require('@google-cloud/datastore');

const projectId = "YOUR_PROJECT_ID";
const datastore = DataStore({projectId});

const data = {name: {forename: 'David', surname: '<YOUR_LONG_STRING>'}, colour: 'purple'}

const Kind = "<YOUR_ENTITY_KIND>";

datastore
  .save({key: datastore.key([Kind]), data: data, excludeFromIndexes: ['name.surname']})
  .then(() => {
    console.log(`Entity saved`);
  })
  .catch(err => {
    console.error('ERROR:', err);
  });

运行这段代码后,如果您检查Datastore dashboard中的实体,您将能够看到我的EmbeddedEntity定义为我在答案开始时分享的内容。