How to customize export using TargetAction?


#1

C3 colleagues,

Please note - I was suggested to create a separate post under this category by author of similar topic, and hence this new topic.

I tried to export data using the TargetAction approach which is similar to the one you have suggested above.
However, I think I have missed one or more important connections. I am not able to get the export working using this approach.
Below are abstracted code snipprts for your reference.

******** Export Function **************************

function exportConfigurationsData() {
  "use strict";
  
  // Below method fetchModelsForProducts() gets some pre configured comma separate string of models, 
  // which is used in the fetch filter used within method Inventory.fetchConfigurations()
  var models = fetchModelsForProducts();
  
  var args = {spec: ConfigurationsExportSpec.make({models: models})};
  var typeName = "Inventory";
  var header = "id,model,groupNumber,name,prefix";
  var path = "s3://" + S3.inst().mountName("DEFAULT") + "/OUT/" + typeName + "/export/";
  
  var spec = BatchExportSpec.make({
    filter: "1==1",
    targetAction: {typeName: "Inventory", actionName: "fetchConfigurations", args: args},
    numFiles: 1,
    contentType: "text/csv",
    csvHeader: header,
    fileUrlOrEncodedPathPrefix: path
  });
  
  return Export.startExport(spec);
}

** Export Input Type ******************************

type ConfigurationsExportSpec {
  ids: [string]
  models: string
}

** Export Output Parent Type **********************

type ConfigurationsExportResult {
  results: [ConfigurationsExportRecord]
}

** Export Output Child Type ***********************

type ConfigurationsExportRecord {
  id: string
  model: string
  groupNumber: string
  name: string
  prefix: string
}

** Inventory.c3typ entity *************************

entity type Inventory {

  exportConfigurationsData: function() js server

  fetchConfigurations: function(spec: ConfigurationsExportSpec): ConfigurationsExportResult js server

}

** Inventory.js ***********************************

function fetchConfigurations(spec) {

	var objects = Inventory.fetch({filter: "intersects(model, ["+spec.models+"])"});
	
	// do complex processing on 'objects' array by performing fetch joins with other types 
	// and then convert it into "records", an array of ConfigurationsExportRecord
	
	return ConfigurationsExportResult.make({results: records});
}

Could you please check and suggest what might be going wrong ?

Cheers,
Mandar


#2

your solution almost looks correct hard to spot where is the problem. Could you try debugging by splitting, e.g. check if with the given models you have in your spec this fetch returns something
Inventory.fetch({filter: "intersects(model, ["+spec.models+"])"})

Also as your target function is on the same type as the original Inventory type was wondering if it’s not an option for you to instead use a MapReduce job, it should be straightforward in your case.


#3

This issue was resolved by a change as explained below.

Instead of defining a type for output such as ‘ConfigurationsExportResult’ type and returning an instance (consider object) of it, (for this specific scenario) the method must simply create an Array using Obj.arry() and push instances of ‘ConfigurationsExportRecord’ (assuming these record objects hold all fields that you want to export)

Modified Code -

** Inventory.c3typ entity *************************

entity type Inventory {

  exportConfigurationsData: function() js server

  fetchConfigurations: function(spec: ConfigurationsExportSpec): [Obj] js server

}

** Inventory.js ***********************************

function fetchConfigurations(spec) {
	var records = Obj.arry();
	var objects = Inventory.fetch({filter: "intersects(model, ["+spec.models+"])"});
	
	// do complex processing on 'objects' array by performing fetch joins with other types 
	// Create instances of ConfigurationsExportRecord using members from 'objects' or whatever the case may be and push/add them to 'records' array

	return records;
}

Reason: As per C3 docs, method Export.startExport(spec), must return an Obj or an Arry of Obj