WixData Query Nested Collections

Hi Everyone,

I want to query a collection "Campaign" and then query all the actions from "Actions" collection which belong to the Campaign.  

Then I count the actions for each campaign and store it in a map.

Finally i am populating the campaigns with counts in a repeater. And all campaigns in the drop down so that I can show more details for each campaign when selected from drop down.

This is my code :

.eq(“isDone”, “true”)
.eq(“_owner”, userId)
.then( (results) => {
console.log(“hello testing this one”);

results.items.forEach((item) => {
var campaign = {label:item.campaignName , value:item._id};
.eq(“templateId”, item._id)
.then( (actions) => {
campaignToActions[item._id] = actions.items;
var count = 0;
var accessed = 0;
actions.items.forEach((action) => {
count = count + 1;
if (action.accessTimestamp !== null ) {
accessed = accessed + 1;
campaignToEmails[item._id] = count;
campaignToViews[item._id] = accessed;

$w(“#repeater1”).data = results.items;
$w(“#dropdown1”).options = campaigns;

When i query Actions inside the for loop, I am using “then” which is async. How can i make sure the last two statements happen only after all the async is complete.


The following is a strategy that you could use. It has to be in an async function, in the page onReady or otherwise. I’ve taken the liberty to change the first query result name to “campaigns” for clarity sake. The idea is to query actions only once. That will speed it up some since you’re not going back and forth from the data server to the front end. With some “if logic”, assign the actions records to the appropriate campaign.

Doing it this way, the code will not advance to the repeater assignment line until all the data gathering and assigning is done.

$w.onReady(async function () {
    const campaigns = await wixData.query("Campaign")
    .eq("isDone", "true")
    .eq("_owner", userId).find();
    const actions = await wixData.query("Actions");
    campaigns.items.forEach((item) => {
        actions.items.forEach((action) => {
            if (item._id === action.templateId){
                // fill in the details
    $w("#repeater1").data = campaigns.items;
    $w("#dropdown1").options = campaigns;

Thank you for the response.

The only concern I have with the above code is, we are querying all the actions from Actions table,but I need only actions related to some Campaigns.

  1. I am worried that we will be using too much memory. Is that a concern I should worry about ??

  2. Is there a way to query all actions for given set of campiagn ids ?

Right, I was going to ask how large Actions is. You could use the hasSome function in the Actions query, feeding it with the campaign ids from the campaign query.

A quick way to get those ids would be to use the Javascript map function.

let Ids = campaigns.items.map(a => a._id);
const actions = await wixData.query(“Actions”).hasSome(“templateId”,Ids);

Thank you so much for the quick response.

I have one more blocker while I am processing the data that i query and setting it in local.
This is related to local storage.

let campaignToEmails = {};
let campaignToViews = {};

local.setItem(“campaignToEmails”, campaignToEmails);
local.setItem(“campaignToViews”, campaignToViews);

The log shows the map of campaign id to views count correctly.
However, in a different function, I do this :
let campaignToEmails = local.getItem(“campaignToEmails”);
let campaignToViews = local.getItem(“campaignToViews”);

The log here just shows object and i can’t get the views with campaign id anymore. Seems like we are not able to cast the map back. Any help on this please ?

Since this is a completely new issue about local storage, I create a new question so that its easy for someone with similar problem to look up.