[JS SDK] Hi, I’m trying to figure out what the bes...
# gooddata-platform
e
[JS SDK] Hi, I’m trying to figure out what the best way to get all the attributes that are valid filter options for an insight is. I’m using the
availableItems()
factory from
IWorkspaceCatalog
using the
forInsight
chained method, but it expects an
IInsightDefinition
and that’s not a kind of object I have unless I create a new insight. Is there a way to do something like
forInsight
but with an insight identifier? Or get an
IInsightDefinition
from an identifier? If not that then what’s the best way to accomplish what I’m trying to do? I should note that I will want to do this for multiple insights at a time so I’m hoping it won’t require too many consecutive calls.
d
Hi, Dan here from the GoodData.UI team. You are on the right track, unfortunately we need the insight data to create the availableItems catatog call. You can use the
getInsight
function in the
insigts
part of the Analytical workspace. Assuming you have the instance of the Analytical backend stored in a variable called
backend
, this should be doing what you are trying to do:
Copy code
import { idRef } from "@gooddata/sdk-model";

async function getAvailableAttributesForInsight(id) {
    const [catalog, insight] = await Promise.all([
        backend.workspace("WORKSPACE_ID").catalog().load(),
        backend.workspace("WORKSPACE_ID").insights().getInsight(idRef(id)),
    ]);

    return catalog.availableItems().forInsight(insight).forTypes(["attribute"]).load();
}

// or for multiple insights
async function getAvailableAttributesForInsights(ids) {
    const [catalog, insights] = await Promise.all([
        backend.workspace("WORKSPACE_ID").catalog().load(),
        Promise.all(ids.map((id) => backend.workspace("WORKSPACE_ID").insights().getInsight(idRef(id)))),
    ]);

    const availableAttributes = await Promise.all(
        insights.map((insight) =>
            catalog.availableItems().forInsight(insight).forTypes(["attribute"]).load(),
        ),
    );

    // return the results as object mapping id -> available attributes
    return ids.reduce((acc, id, index) => {
        acc[id] = availableAttributes[index];
        return acc;
    }, {});
}
The functions shown try to do as much network requests in parallel as possible. Hope this helps!
e
Thanks Dan! This works but now I have a new problem. It seems that these availableItems loads are querying gooddata for comprehensive information on each related attribute, which for longer lists of attributes is causing me to very quickly run into throttling issues and visible slowdown on my page. I already have the catalog loaded from earlier in my app’s life cycle, so these extra requests are not necessary. Is there a way to just get a list of attribute identifiers? Or even just the object URI id? Then I just have to compare against the preloaded catalog. Edit: Looking closer at these network calls it seems to be requests for all manner of object types. Either way it’s a lot more than just the 2n+1 number of calls I was expecting.
d
Your propsed solution is how the availableCatalogItems works internally: it gets the uris/ids of available items and filters the already loaded data. To optimize your case, you can “reuse” the already loaded catalog:
Copy code
// load the whole catalog once
const catalog = await backend.workspace("WORKSPACE_ID").catalog().load();

// just for illustration, these can be parallelized by Promise.all or other means
const insight1 = await backend.workspace("WORKSPACE_ID").insights().getInsight(idRef("INSIGHT1_ID"));
const insight2 = await backend.workspace("WORKSPACE_ID").insights().getInsight(idRef("INSIGHT2_ID"));

// you can reuse the `catalog` object so that the preloaded data is reused as well and only data needed to filter them
// according to the individual insights is downloaded
const insight1AvailableAttrs = await catalog.availableItems().forInsight(insight1).forTypes(["attribute"]).load();
const insight2AvailableAttrs = await catalog.availableItems().forInsight(insight2).forTypes(["attribute"]).load();
Does this help you or am I missing something?
e
Ok, good to know. Thanks!
d
No problem 🙂