纯javascript(es2015)函数,用于从树json结构中提取子级



我有一个DocumentDb数据库,其中一种文档类型具有以下结构:

{
"structure": {
"id": "7d2d5d3f-0c82-4910-aa0b-54d8067588a3",
"unittype": 1,
"name": "MyCompany",
"language": "nb-NO",
"managers": [],
"logoURL": null,
"orginfo": {
"Orgnumber": null,
"Country": null,
"Sector": null,
"Code": null
},
"tags": [],
"respondents": [],
"childUnits": [
{
"id": "3fb44416-8fa8-4b60-8c0c-03b333d176f7",
"unittype": 3,
"name": "Marketing",
"language": "nb-NO",
"managers": [],
"logoURL": null,
"orginfo": {
"Orgnumber": null,
"Country": null,
"Sector": null,
"Code": null
},
"tags": [],
"respondents": [],
"childUnits": [
{
"id": "49932d6f-518e-4511-9bc9-f6f747a81968",
"unittype": 3,
"name": "Internet",
"language": "nb-NO",
"managers": [],
"logoURL": null,
"orginfo": {
"Orgnumber": null,
"Country": null,
"Sector": null,
"Code": null
},
"tags": [],
"respondents": [],
"childUnits": [],
"Parent": "3fb44416-8fa8-4b60-8c0c-03b333d176f7"
},
{
"id": "aa76010d-ae59-49b1-b929-9572eb536cc6",
"unittype": 3,
"name": "DM",
"language": "nb-NO",
"managers": [],
"logoURL": null,
"orginfo": {
"Orgnumber": null,
"Country": null,
"Sector": null,
"Code": null
},
"tags": [],
"respondents": [],
"childUnits": [],
"Parent": "3fb44416-8fa8-4b60-8c0c-03b333d176f7"
}
],
"Parent": "7d2d5d3f-0c82-4910-aa0b-54d8067588a3"
},
{
"id": "be1d142a-e09d-4828-aceb-07d65321da5d",
"unittype": 3,
"name": "Support",
"language": "nb-NO",
"managers": [],
"logoURL": null,
"orginfo": {
"Orgnumber": null,
"Country": null,
"Sector": null,
"Code": null
},
"tags": [],
"respondents": [],
"childUnits": [],
"Parent": "7d2d5d3f-0c82-4910-aa0b-54d8067588a3"
}
],
"Parent": null
},
"id": "07b4c7c5-7324-4eef-9e4e-9deb70615ec4",
"type": "organization",
"owner": "auth0|571f2eb34247998a66726b02",
"public": false,
"_rid": "GPFbALqREAMNAAAAAAAAAA==",
"_self": "dbs/GPFbAA==/colls/GPFbALqREAM=/docs/GPFbALqREAMNAAAAAAAAAA==/",
"_etag": ""00004707-0000-0000-0000-5881cef40000"",
"_attachments": "attachments/",
"_ts": 1484902132
}

这是对旧系统的重建,其中所有内容都存储在关系数据库中,每个Unit(childUnits属性中的对象)最初都是表中的一行。与我们最大的客户之一进行测试,我们最终得到了一个拥有500多个单元的结构。超过3000名受访者。(我在这个演示中没有添加任何内容,但Respondent对象包括一封电子邮件(必需),可能还有一个手机号码。)

结果不好。在我(相当健壮)的devpc上本地运行,结构的检索大约需要2-3秒。DocumentDb不支持检索文档部分。因此,每当用户点击树视图中的一个单元时,整个结构都会通过网络重新发送(这部分我可能可以缓存,但如果用户更改了什么,我必须存储整个内容,然后读回)。

然而,DocumentDb所支持的是Javascript存储过程,它使用Chakra,据我所见,Chakra符合ES2015。

因此,我的想法是创建一个存储过程,我将id赋予文档(组织),将id赋予单元进行检索。它搜索json文档,只检索我想要的单元并将其发回。

这可能不使用外部库,只使用ES2015功能吗?

性能的最佳方法是利用文档内的JOIN-https://www.documentdb.com/sql/demo#JOIN.

假设structure属性实际上是文档的一部分,那么JOIN查询将如下所示:

SELECT c.id, childUnit 
FROM c JOIN childUnit IN c.structure.childUnits 
WHERE c.structure.id = "7d2d5d3f-0c82-4910-aa0b-54d8067588a3" 
AND childUnit.id = "3fb44416-8fa8-4b60-8c0c-03b333d176f7"*

如果结构属性实际上不是原始文档的一部分,那么JOIN查询将如下所示:

SELECT c.id, childUnit 
FROM c JOIN childUnit IN c.childUnits 
WHERE c.id = "7d2d5d3f-0c82-4910-aa0b-54d8067588a3" 
AND childUnit.id = "3fb44416-8fa8-4b60-8c0c-03b333d176f7"*

这种类型的查询将只返回文档中指定的子单元。WHERE筛选器中的单元id子单元id提高查询性能。

Array.prototype.find解决了大多数这些问题。

如果需要,您可以使用polyfill函数:MDN官方polyfill。

var db = {
"structure": {
"id": "7d2d5d3f-0c82-4910-aa0b-54d8067588a3",
"unittype": 1,
"name": "MyCompany",
"language": "nb-NO",
"managers": [],
"logoURL": null,
"orginfo": {
"Orgnumber": null,
"Country": null,
"Sector": null,
"Code": null
},
"tags": [],
"respondents": [],
"childUnits": [
{
"id": "3fb44416-8fa8-4b60-8c0c-03b333d176f7",
"unittype": 3,
"name": "Marketing",
"language": "nb-NO",
"managers": [],
"logoURL": null,
"orginfo": {
"Orgnumber": null,
"Country": null,
"Sector": null,
"Code": null
},
"tags": [],
"respondents": [],
"childUnits": [
{
"id": "49932d6f-518e-4511-9bc9-f6f747a81968",
"unittype": 3,
"name": "Internet",
"language": "nb-NO",
"managers": [],
"logoURL": null,
"orginfo": {
"Orgnumber": null,
"Country": null,
"Sector": null,
"Code": null
},
"tags": [],
"respondents": [],
"childUnits": [],
"Parent": "3fb44416-8fa8-4b60-8c0c-03b333d176f7"
},
{
"id": "aa76010d-ae59-49b1-b929-9572eb536cc6",
"unittype": 3,
"name": "DM",
"language": "nb-NO",
"managers": [],
"logoURL": null,
"orginfo": {
"Orgnumber": null,
"Country": null,
"Sector": null,
"Code": null
},
"tags": [],
"respondents": [],
"childUnits": [],
"Parent": "3fb44416-8fa8-4b60-8c0c-03b333d176f7"
}
],
"Parent": "7d2d5d3f-0c82-4910-aa0b-54d8067588a3"
},
{
"id": "be1d142a-e09d-4828-aceb-07d65321da5d",
"unittype": 3,
"name": "Support",
"language": "nb-NO",
"managers": [],
"logoURL": null,
"orginfo": {
"Orgnumber": null,
"Country": null,
"Sector": null,
"Code": null
},
"tags": [],
"respondents": [],
"childUnits": [],
"Parent": "7d2d5d3f-0c82-4910-aa0b-54d8067588a3"
}
],
"Parent": null
},
"id": "07b4c7c5-7324-4eef-9e4e-9deb70615ec4",
"type": "organization",
"owner": "auth0|571f2eb34247998a66726b02",
"public": false,
"_rid": "GPFbALqREAMNAAAAAAAAAA==",
"_self": "dbs/GPFbAA==/colls/GPFbALqREAM=/docs/GPFbALqREAMNAAAAAAAAAA==/",
"_etag": ""00004707-0000-0000-0000-5881cef40000"",
"_attachments": "attachments/",
"_ts": 1484902132
};
function getDocument(orgID, docID) {
//Variable to hold traversal progress
var extract = db
.structure
.childUnits
.find(function findFunc(organization) {
return organization.id == orgID;
});
//Return false if we found no organization
if (typeof extract == "undefined") {
return false;
}
//Traverse organization children
extract = extract
.childUnits
.find(function findFunc(document) {
return document.id == docID;
});
//Return false if we found no organization
if (typeof extract == "undefined") {
return false;
}
//if we reach this point we found a result, which we can then return
return extract;
}
//Running test
console.log(getDocument("3fb44416-8fa8-4b60-8c0c-03b333d176f7", "aa76010d-ae59-49b1-b929-9572eb536cc6"));
console.log(getDocument("3fb44416-8fa8-4b60-8c0c-03b333d176f7", "ERR"));
console.log(getDocument("ERR", "aa76010d-ae59-49b1-b929-9572eb536cc6"));
console.log(getDocument("ERR", "ERR"));

您可以使用具有迭代和递归风格的Array#some

function getObject(object, id) {
var r;
return function iter(o) {
if (o.id === id) {
r = o;
return true;
}
if (Array.isArray(o.childUnits)) {
return o.childUnits.some(iter);
}
}(object) && r || undefined;
}
var data = { structure: { id: "7d2d5d3f-0c82-4910-aa0b-54d8067588a3", unittype: 1, name: "MyCompany", language: "nb-NO", managers: [], logoURL: null, orginfo: { Orgnumber: null, Country: null, Sector: null, Code: null }, tags: [], respondents: [], childUnits: [{ id: "3fb44416-8fa8-4b60-8c0c-03b333d176f7", unittype: 3, name: "Marketing", language: "nb-NO", managers: [], logoURL: null, orginfo: { Orgnumber: null, Country: null, Sector: null, Code: null }, tags: [], respondents: [], childUnits: [{ id: "49932d6f-518e-4511-9bc9-f6f747a81968", unittype: 3, name: "Internet", language: "nb-NO", managers: [], logoURL: null, orginfo: { Orgnumber: null, Country: null, Sector: null, Code: null }, tags: [], respondents: [], childUnits: [], Parent: "3fb44416-8fa8-4b60-8c0c-03b333d176f7" }, { id: "aa76010d-ae59-49b1-b929-9572eb536cc6", unittype: 3, name: "DM", language: "nb-NO", managers: [], logoURL: null, orginfo: { Orgnumber: null, Country: null, Sector: null, Code: null }, tags: [], respondents: [], childUnits: [], Parent: "3fb44416-8fa8-4b60-8c0c-03b333d176f7" }], Parent: "7d2d5d3f-0c82-4910-aa0b-54d8067588a3" }, { id: "be1d142a-e09d-4828-aceb-07d65321da5d", unittype: 3, name: "Support", language: "nb-NO", managers: [], logoURL: null, orginfo: { Orgnumber: null, Country: null, Sector: null, Code: null }, tags: [], respondents: [], childUnits: [], Parent: "7d2d5d3f-0c82-4910-aa0b-54d8067588a3" }], Parent: null }, id: "07b4c7c5-7324-4eef-9e4e-9deb70615ec4", type: "organization", owner: "auth0|571f2eb34247998a66726b02", public: false, _rid: "GPFbALqREAMNAAAAAAAAAA==", _self: "dbs/GPFbAA==/colls/GPFbALqREAM=/docs/GPFbALqREAMNAAAAAAAAAA==/", _etag: ""00004707-0000-0000-0000-5881cef40000"", _attachments: "attachments/", _ts: 1484902132 };
console.log(getObject(data.structure, 'foo'));
console.log(getObject(data.structure, 'aa76010d-ae59-49b1-b929-9572eb536cc6'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

最新更新