在数据存储区的嵌入式实体中使用 excludeFromIndexes 的正确方法是什么
What's the right way to use excludeFromIndexes in an Embedded Entity in Datastore
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);
});
经过一些测试,我能够实现你想要做的事情。我还编辑了你的问题,为了让这个 post 的未来读者更清楚,因为你指的是“属性 part of another 属性”,但它在 Datastore 中定义为 EmbeddedEntity,因此我将坚持使用该名称以获得更清晰的解释。
嵌入式实体可以具有超过 1500 字节的子属性,但您必须明确排除这些子属性,否则将显示错误。为此,您必须将每个 EmbeddedEntity 声明为:
{
"properties": {
"surname": {
"stringValue": "A long surname which has more than 1500B",
"excludeFromIndexes": true
},
"forename": {
"stringValue": "David"
}
}
}
但是使用 NodeJS 以编程方式声明 "excludeFromIndexes": true
并不是很简单。但是最后我设法解决了它。关键是 save()
函数,您可以在其中声明要从索引中排除的 properties 和 subproperties,例如:
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 是我在回答开头分享的定义.
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);
});
经过一些测试,我能够实现你想要做的事情。我还编辑了你的问题,为了让这个 post 的未来读者更清楚,因为你指的是“属性 part of another 属性”,但它在 Datastore 中定义为 EmbeddedEntity,因此我将坚持使用该名称以获得更清晰的解释。
嵌入式实体可以具有超过 1500 字节的子属性,但您必须明确排除这些子属性,否则将显示错误。为此,您必须将每个 EmbeddedEntity 声明为:
{
"properties": {
"surname": {
"stringValue": "A long surname which has more than 1500B",
"excludeFromIndexes": true
},
"forename": {
"stringValue": "David"
}
}
}
但是使用 NodeJS 以编程方式声明 "excludeFromIndexes": true
并不是很简单。但是最后我设法解决了它。关键是 save()
函数,您可以在其中声明要从索引中排除的 properties 和 subproperties,例如:
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 是我在回答开头分享的定义.