FSM Searches and Field Mapping

Field Service Management (FSM) configuration uses NetSuite searches to retrieve jobs, records, and option lists. Field mappings determine which values are returned and, for editable FSM Mobile resources, which NetSuite fields receive the saved values.

A search filter selects records. A map defines the values returned from those records. A map can also define the destination fields used when saving a resource's record. Changing a filter does not create a field mapping, and adding an element does not necessarily map its value to a NetSuite field.

This topic covers:

Where Searches and Maps Are Configured

The following locations serve different purposes. Paths in this table start within the "routes/mobile" configuration object.

Configuration Location

Purpose

event.article.task.filters and .map

Select CRM Task events and provide their event data.

event.article.projecttask.filters and .map

Select Project Task events and provide their event data.

user.employee.map

Provide mapped data for employees. The standard employee search uses user.employee.filters, but a custom override of those filters is removed before configuration merging.

<resource ID>.article.filters and .map

Select the records displayed by a resource and map their values for loading and saving.

<resource ID>.article.filterby

Select a subset of the retrieved articles by matching their mapped properties.

<resource ID>.element.<element name>.options

Supply an option list, such as the choices in a Select element.

<resource ID>.element.<element name>.value

Supply an element's value from a search where that value has a compatible data shape.

<resource ID>.element.<element name>.map

Supply an element's mapping when the resource uses Automap and no matching article mapping already exists.

Event Data and Resource Record Data

For properties removed before merging, including the employee-filter restriction, see How Custom Configuration Combines with Core Configuration in FSM Configuration.

An event map, such as event.article.task.map or event.article.projecttask.map, supplies information about the current job or event in FSM Mobile. Its property names identify values available through event, such as event.customer or event.supportcase. These names can differ from the NetSuite field IDs used to retrieve the values.

A resource's article.map instead supplies values for the record displayed or edited by that resource. Its property names should match the element names that display or edit those values.

For example, the standard CRM Task event map reads the linked case ID from case.internalid and uses supportcase as the write field. A resource can use the resulting event data to filter its own records. Adding a property to the event map does not automatically add an element or a save mapping to that resource.

Use FSM Expressions and Template Tags for the syntax and scope of event, user, and template tags. Preserve the standard event properties and filters required by existing FSM Mobile behavior when extending an event definition.

Defining a Search

A search definition identifies a NetSuite record type, the records to select, and the values to return. The following table describes its properties.

Property

Accepted Value

Default When Omitted

Effect

record

NetSuite record type ID, such as task, supportcase, or item.

No record type is supplied by the search definition itself.

Identifies the records to search.

filters

NetSuite filter expression, mapped filter object, internal ID or array of IDs, or true.

The standard search helper supplies an inactive-record filter when no filters are supplied. Other configuration can supply filters before the search runs.

Restricts the results. Use explicit filters appropriate to the record type. See Other Filter Forms.

map

Mapping string, object, or array.

The standard search helper returns internal IDs. Article models can add their own ID mapping.

Defines the returned values and their shape.

objectify

true or false, for resolved template-data searches.

true in standard search retrieval, unless an effective definition sets false.

Selects mapped values or native search results. See Returning Mapped Values or Native Search Results.

all

true or false.

false in standard search retrieval.

Enables retrieval beyond the first 1,000 search rows in supported locations. See Retrieving More Than 1,000 Results.

result

A nonnegative integer identifying a result position, starting at 0.

The complete retrieved result array.

In a resolved search, returns only the mapped value at that position. See Selecting One Search Result.

cache

true or false.

true for resolved searches, unless the calling operation overrides it.

In a resolved search, permits reuse of matching results available in the server search cache. See Reusing Search Results.

The following search can supply Select options for CRM tasks assigned to the employee currently signed in to FSM Mobile. Each option contains the task's internal ID and title:

            {
  "record": "task",
  "filters": ["assigned", "anyof", "${user.internalid}"],
  "all": true,
  "map": {
    "id": "internalid",
    "label": "title"
  }
} 

          

Place this object in an element's options property, or in a loaded supporting resource that supplies shared options. It is a search definition, rather than a complete configuration file.

The search must be valid for the selected record type and the permissions used to execute it. Use NetSuite field and join IDs, rather than field labels shown on a form. A field available on a record form is not necessarily available as a search column with the same ID.

Selecting One Search Result

For a resolved search, such as an element's value search, result: 0 returns the first mapped value rather than an array containing that value. result: 1 returns the second value, and so on. It does not limit the underlying search to that many rows.

The following search definition can supply a single Select value for the case linked to the current event:

              {
  "record": "supportcase",
  "filters": ["internalid", "anyof", "${ event.supportcase || 0 }"],
  "map": {
    "id": "internalid",
    "label": "casenumber"
  },
  "result": 0
} 

            

Place this object in the Select element's value property. Its options must separately provide the available choices. If the search returns no row at the requested position, it supplies no value. The result property does not provide a fallback. When more than one record can match, define the search order before relying on the first result. This property is not a result-selection control for a direct article model.

The following fragment shows the default flags for a resolved template-data search. To complete the search definition, supply its record, filters, and required map:

              {
  "objectify": true,
  "all": false,
  "cache": true
} 

            

Selecting Records with Filters

A filter condition normally contains a search field, an operator, and the comparison value. Combine conditions with and or or. Use nested arrays to make the intended grouping explicit.

The following CRM Task filter restricts results to tasks assigned to the current employee that have a linked case:

            [
  ["assigned", "anyof", "${user.internalid}"],
  "and",
  ["case.internalid", "noneof", "@NONE@"]
] 

          

The valid operators and comparison values depend on the field type. For example, a List/Record field typically uses an internal ID with anyof. A checkbox uses a value such as "T" or "F" with is. Search joins must be available for the searched record type.

Template tags can supply values from the current context. Ensure that a tag resolves to a value accepted by the filter. See FSM Expressions and Template Tags for substitution and value-type rules.

Mapped Filter Objects

A filter object can use names defined in the same map. For example:

              {
  "record": "task",
  "filters": {
    "caseId": "${event.supportcase}"
  },
  "map": {
    "id": "internalid",
    "caseId": "case.internalid[record]"
  }
} 

            

Here, the caseId map identifies the search field and its List/Record format. The helper uses that information to build the filter. Use this example only where the event supplies a linked case ID. For more complex conditions, an explicit filter expression makes the operator and grouping clearer.

An explicitly supplied filter array replaces an inherited filter array when configuration is merged. Include every condition that must remain. In particular, preserve restrictions that associate records with the current job, employee, customer, or asset.

Overriding a product-supplied search can change downstream processing as well as the displayed results. Consider the affected processing paths and configuration choices when changing filters or mappings. For example, changes to Consumable inventory options can expose unavailable or inconsistent stock details. With automatic fulfillment enabled, resulting processing errors can exclude related case work from later processing. An override does not necessarily fail. For the capability-specific risks and choices, see Inventory Search Overrides and Processing Risks in Configuring FSM Consumable Processing.

Parent Relationships

For a resource that uses article.parent, FSM supplies a parent filter when article.filters is not already supplied. If you configure your own filters, include the required parent restriction yourself. Setting article.parent still supplies the parent value for new records. This property does not add the parent restriction to an existing custom filter expression.

Other Filter Forms

The following table lists the filter forms accepted by the standard search helper.

Value

Resulting Condition

An internal ID, such as 123 or "123".

internalid anyof that ID.

An array of internal IDs, such as [123, 456].

internalid anyof those IDs.

true.

internalid noneof @NONE@. This condition does not restrict the search to active records.

For context that may be missing, prefer an explicit filter expression with a nonmatching ID value, as in ["internalid", "anyof", "${ event.supportcase || 0 }"]. A direct filters: 0 enters the helper's default-filter path. This setting does not mean a search for internal ID zero. Preserve the other record restrictions needed for the intended behavior.

Filtering Mapped Articles with filterby

Use article.filterby to select a subset of articles after their search results have been retrieved and mapped. Each property name must identify a top-level property in the mapped article, such as id or asset. The article is retained only when every specified property matches its comparison value.

The following table compares the stages at which filters and filterby apply.

Property

Names Used

Effect

filters

NetSuite search fields or mapped filter names.

Restricts the records retrieved by the NetSuite search, using search operators.

filterby

Top-level mapped article property names.

Matches the retrieved articles against the supplied values. It does not add a NetSuite search condition or group results.

Use individual values for matching. filterby does not accept NetSuite filter operators, conditions joined with and or or, or a list of alternative values for one property. A property containing a nested Select object should be mapped to an individual value before using it for this matching.

For example, the standard Consumables resource searches for the current event's Consumable records belonging to the current employee. Its article.map returns the linked asset as asset, and its article.filterby selects the records for the requested asset:

            {
  "filterby": {
    "asset": "${ options.asset || event.asset }"
  }
} 

          

This fragment belongs within routes/mobile.consumables.article. FSM uses the request's asset when supplied. Otherwise, FSM uses the current event's asset. The fragment reproduces the standard property, rather than defining the complete resource. Preserve its existing filters and map when configuring related behavior. Omitting filterby from custom JSON retains any inherited standard definition.

This separation allows the same underlying search results to be reused for different asset selections when caching is available. Changing only filterby does not change the search cache key. Moving the asset condition into filters changes the underlying search and its cache key. The more selective search may retrieve less data, and filterby may avoid repeating a shared search. Measure the effect for the intended use.

Continue to use filters for the required event, employee, customer, and other record restrictions. Because filterby runs after retrieval, it does not reduce the rows searched or extend the retrieval limit. It can return fewer articles than the search retrieved. It applies to article record models, including individual named sources. This property is not applied by a resolved element options or value search.

Reusing Search Results

FSM can reuse previously retrieved results when search caching is enabled and matching results remain available to the server execution. The search cache compares the record type, processed filters, map, saved-search identifier where used, raw or mapped result mode, and all setting. filterby is applied after cache retrieval and is not part of this key.

For resolved searches, such as element options and value searches, caching defaults to true. Setting cache: false on that search bypasses both reading and writing its search-cache entry. Standard resource article loading also requests cached search results. Adding cache to a direct article definition does not control caching for that loading operation.

Preserve common search definitions that provide the required behavior. Avoid changing filters or maps between otherwise identical calls unnecessarily. For repeated asset requests that need different subsets of the same eligible records, retain the standard filterby relationship. Use an alternative only if measurements show that it improves performance and preserves the behavior.

The server search cache and the data already loaded into FSM Mobile are separate mechanisms. Do not assume that search-cache reuse eliminates an FSM Mobile request, persists between requests, or guarantees fresh data after a record changes. For the planned guidance on cache scope, freshness, measurement, and related best practices, see FSM Performance and Data Collection.

Reducing Formula Use

Important:

Measuring actual search performance in the account is the best indicator of whether a search needs optimization and whether a replacement improves it. Formula use alone does not establish a performance problem, and configuration or source review cannot reliably identify every search that may be slow. Compare performance using representative data and user actions, and confirm that the required results are preserved.

Search formulas, including formulatext, formulanumeric, formuladate, and formuladatetime, can slow search execution. Prefer standard NetSuite field or joined-field filters, using template tags to supply values from the current context. Add JavaScript inside a template tag only when additional logic is required and a search formula would otherwise be needed. Keep that JavaScript as simple as possible.

For example, standard filters can compare a quote's project and case IDs with values supplied by ${ event.job } and ${ event.supportcase }. Simple fallback logic can handle missing IDs before the search runs. NetSuite performs the record filtering. See FSM Expressions and Template Tags for template-tag syntax and evaluation.

This approach applies when the required inputs are already available in the template context. A template tag does not automatically have the field values of every record being searched. Retain a formula where its calculation cannot be replaced without changing the returned records or values. For result mappings, use direct or joined field mappings that provide the required value.

Example: Selecting Quotes for the Current Job

The standard Quote resource searches NetSuite estimate records. Its filters include quotes linked directly to the current CRM Task or Project Task, and quotes whose project and case both match the current event. The project-and-case condition uses this formula filter:

              [
  "formulatext:case when ({job.internalid} = '${ event.job }') and {custbody_nx_case.internalid} = '${ event.supportcase }' then 'T' else 'F' end",
  "is",
  "T"
] 

            

The formula also avoids passing missing project or case IDs to standard filters. A replacement must preserve that behavior and the direct task links.

The following custom configuration illustrates an alternative for routes/mobile.quote.article.filters. It uses ordinary search conditions and short template tags to supply the IDs:

              {
  "routes/mobile": {
    "quote": {
      "article": {
        "record": "estimate",
        "filters": [
          ["custbody_nx_task", "is", "${ event.internalid }"],
          "or",
          ["custbody_nx_projecttask", "is", "${ event.internalid }"],
          "or",
          [
            ["job.internalid", "anyof", "${ event.job || 0 }"],
            "and",
            ["custbody_nx_case", "anyof", "${ event.supportcase || 0 }"]
          ]
        ]
      }
    }
  }
} 

            

The example preserves or changes the following aspects of the search:

  • Quotes linked directly to the current CRM Task or Project Task remain included.

  • When both project and case IDs are available, the additional branch requires both to match. It does not select every quote for either one separately.

  • The case condition reads the stored custbody_nx_case field directly, rather than joining to the case record to read its internal ID. The project condition retains job.internalid, the transaction search's project join.

  • When a project or case ID is missing or blank, || 0 supplies a nonmatching ID. That project-and-case branch cannot match. The direct task conditions remain available. Do not substitute @NONE@: it can match records with an empty link.

  • record: "estimate" restricts the search to estimate records, so a second recordtype condition is unnecessary.

  • The example replaces the filter formula. Formula mappings elsewhere in the Quote resource remain in use.

This example shows an alternative configuration. It does not describe a change to the standard Quote search. Custom filter arrays replace the inherited array. Before using the example, review the combined configuration and preserve any additional restrictions required by the account.

Checking a Formula Replacement

A replacement must preserve the required result set. Use selective standard NetSuite filters and template tags. Retrieving broader results and filtering the results afterward in JavaScript can increase retrieval time, payload size, and the risk of search limits.

Measured search performance is the best indicator of improvement. Replacing a formula does not guarantee better performance. See FSM Performance and Data Collection for measurement and collection methods.

Mapping Search Results

In an object map, each property name identifies a returned value. Its mapping string identifies the NetSuite search column or formula that supplies that value.

            {
  "record": "task",
  "filters": ["internalid", "anyof", "${event.internalid}"],
  "map": {
    "id": "internalid",
    "title": "title",
    "caseId": "case.internalid",
    "statusText": "status#"
  }
} 

          

This example applies to a CRM Task event. Each returned object has the property names id, title, caseId, and statusText. The joined search column case.internalid supplies the linked case ID. The # flag reads the displayed status text instead of its stored value.

The following table shows how the map's shape affects the result.

Map Shape

Result from a Resolved Search

A string, such as "internalid".

An array of individual values, one for each returned row.

An object, such as { "id": "internalid", "label": "title" }.

An array of objects with the configured property names.

An array, such as ["internalid", "title"].

An array containing an array of mapped values for each returned row.

A search returning no rows produces an empty array. The Select's selected value is separate from its options: returning choices does not map the chosen value back to a record field.

Mapping Flags

Flags change how a mapping is read or written. Their placement on the read or write side of a mapping matters.

Flag

Effect

#

Read the field's display text. On a write mapping, set the field by text instead of its stored value.

[]

Read or write an array of values, such as a multiselect field. The [] flag does not map a transaction sublist.

=

Identify the primary value in a mapped object, such as the ID in a Select value.

*

Merge search rows with the same mapped key into one result object.

<

Sort the search column in ascending order.

>

Sort the search column in descending order.

^

Group the search column.

?

Count the search column.

+

Sum the search column.

~

Average the search column.

{

Return the minimum search-column value.

}

Return the maximum search-column value.

!

Force a field write even when its current value compares equal to the supplied value.

The | separator assigns different read and write mappings. See Reading and Saving Different Fields.

The = and * flags control the enclosing mapped object through its first string mapping. Place the primary or merge-key mapping first in that object. Reordering these entries can change the result even when the individual mapping strings remain unchanged.

Mapping Formats

A format suffix can convert a mapped value for reading, writing, or filtering. For example, "internalid[integer]" reads an integer, and "isinactive[boolean]" reads a Boolean value.

The following table lists common formats.

Suffix

Purpose

[string]

Treat the value as text.

[boolean]

Convert a NetSuite checkbox value to or from a Boolean value.

[integer]

Convert a whole-number value.

[float]

Convert a decimal-number value.

[record]

Apply List/Record value formatting and filtering.

[date], [time], [datetime]

Apply the corresponding temporal format.

Choose a format appropriate to the NetSuite field and the receiving element. A format does not make an invalid field ID valid or change the underlying NetSuite field type. Temporal values and element validation are described in FSM Mobile Element (Block) Reference.

Returning Mapped Values or Native Search Results

objectify controls whether standard search retrieval converts results using the map. Its default is true. In configuration, this property is useful for resolved searches supplying report or email template data.

Setting

Returned Data

Effect of an Object Map

true, or omitted from the effective search definition

Values read and converted using the map.

The map's property names become the returned object's property names.

false

Native NetSuite search results.

Map values select search columns. Map property names do not rename the native results.

For example, "duration": "durationdecimal" produces a mapped property named duration when objectification is enabled. With objectify: false, a native-result template instead references the search column durationdecimal.

The native-results path skips FSM's mapped-value conversions and mapped duplicate-row merging. Sorting and summary operations defined on the search columns still apply. The consumer must accept native search results. These results cannot replace the mapped objects expected by FSM Mobile articles or Select options.

Omitting the property from custom JSON retains any inherited value. Check the effective definition before changing it.

For standard report settings and matching XML examples, see Search Results and objectify and Field Names in Report Templates in FSM Service Report Configuration.

Reading and Saving Different Fields

A mapping can read a search column and save to a different record field. Place the read mapping before | and the write mapping after it.

Mapping

Read Behavior

Save Behavior

"title"

Read the title search column.

Write the title record field.

"case.internalid|supportcase"

Read the linked case ID through the search join.

Write the task's supportcase field.

"status#|"

Read the displayed status text.

Do not write a destination field.

"|message"

Do not supply a search-column value.

Write the task's message field when a value is supplied.

Without a pipe, a plain field mapping uses the same name for reading and writing. A formula mapping without an explicit write destination is read-only.

For example, this resource article map reads and saves notes through the task's message field and displays status without writing it:

            {
  "notes": "message",
  "statusLabel": "status#|"
} 

          

The resource's elements would be named notes and statusLabel. If an element is renamed, update its article mapping as well.

A read-only mapping and an element's readonly property have different purposes. The mapping controls the NetSuite write destination. The element property controls editing in the FSM Mobile interface. If a displayed value should not be edited, configure the element accordingly.

Important:

Mapping display text back to a List/Record field can depend on its available labels. Prefer internal IDs for saved selections. Use ! only when a field must be set again: forcing an otherwise unchanged write can trigger field-change processing.

Mapping Select Values

A single Select uses an object containing an id and a label. A Select with multiple: true uses an array of these objects. Its options and its saved value must have compatible shapes.

Single Selection

The following map entry reads an FSM Task Type selection and writes the selected ID back to the task:

              {
  "taskType": {
    "id": "=custevent_nx_task_type",
    "label": "custevent_nx_task_type#|"
  }
} 

            

The id entry is first. The = flag identifies it as the object's primary value. FSM returns the selection object when the ID is populated. An empty primary value produces null. On save, the selected ID is written to custevent_nx_task_type. The label is for display.

The = flag is not required simply to read an ordinary field's stored value. It is used here to control how the selection object is loaded and saved.

Multiple Selections

The following illustrates a custom multiselect field. Replace custrecord_example_services with the multiselect field ID on the resource's record type:

              {
  "selectedServices": {
    "id": "custrecord_example_services=[]",
    "label": "custrecord_example_services#[]|"
  }
} 

            

The ID mapping combines = and []. FSM pairs the returned IDs and labels to produce an array of selection objects. Saving the value writes the selected IDs to the multiselect field. An empty selection is represented by an empty array.

This mapping is for a multiselect field. A Table element representing sublist lines needs a separate array mapping. See Mapping Table Values to Sublists.

Using Automatic Field Mapping

Automap generates missing article mappings for a resource's top-level elements that carry values. It uses the element name and type, or the element's explicit map property.

Resource Configuration

Automap Behavior

form is supplied and automap is omitted.

Enabled. This includes "form": {}.

form is supplied and automap is false.

Disabled.

form is omitted and automap is omitted or false.

Disabled.

automap is true.

Enabled for the resource's eligible elements.

When enabled, Automap uses the following precedence for each eligible element:

  1. Keep the matching entry already defined in article.map.

  2. If that entry is absent, use the element's map property when supplied.

  3. Otherwise, generate a mapping from the element's name and type.

For example, a Text element normally maps to the field with the same name. A Select uses an ID-and-label object mapping. Its multiple property determines whether the selected value is an object or an array. File and Image elements use mappings that include the selected file ID and its address.

An element's map property is used through Automap. If Automap is disabled, define the required mapping in article.map. Automap does not infer the child-field mappings needed to save a Table to a NetSuite sublist.

Mapping an Element with a Different Name

The following fragment shows an element named notes mapped to the task's message field:

              {
  "automap": true,
  "article": {
    "record": "task",
    "filters": ["internalid", "anyof", "${event.internalid}"]
  },
  "element": {
    "notes": {
      "type": "textarea",
      "label": "Task Notes",
      "map": "message"
    }
  }
} 

            

This example is a resource fragment for a CRM Task event. Automap creates the notes entry in article.map from the element's mapping. An explicit article.map.notes would take precedence over that element mapping.

Important:

Automap generates mappings. It does not check that the target field exists or is searchable. Use valid fields for article.record. Give a display-only element an appropriate explicit mapping or exclude it from automatic field mapping. An invalid generated search column can prevent the resource from loading.

Form loading and generated element properties are described in FSM Mobile Element (Block) Reference. Search mappings supply record data. Form-generated initial values and element validation are separate considerations.

Using Formulas in Maps

Prefer direct or joined field mappings that provide the required value. See Reducing Formula Use for the performance recommendation and an example of replacing a formula filter.

A formula mapping starts with the NetSuite formula column type, followed by : and the formula. Use a formula type appropriate to the returned value, such as formulatext for text or formulanumeric for numbers.

            {
  "label": "formulatext:{title}||' ('||{internalid}||')'",
  "notesPreview": "formulatext:SUBSTR({message},1,250)"
} 

          

The first entry combines the task's title and ID into display text. The second returns the first 250 characters of its message. Both entries are read-only because neither entry has a write destination.

The || inside a formula concatenates SQL text values. It differs from the single | that separates a mapping's read and write sides. Formula field references, such as {message}, also differ from FSM template tags, such as ${event.internalid}.

NetSuite evaluates search formulas. FSM Mobile expressions evaluate properties in the FSM Mobile form. Use FSM Expressions and Template Tags for those expression and template mechanisms.

Formula and Text Limits

NetSuite search text columns have a 4,000-byte result limit. This is not a guarantee of 4,000 characters when text contains multibyte characters. See Search Result Limits.

When only a short preview is required, truncate the source text before using it in longer text operations. If several long fields are combined, limit the individual inputs and allow for separators in the combined result. Truncating the final result alone does not necessarily avoid an error in an earlier operation. A preview mapping does not preserve or update the full source text.

Regular-expression patterns have their own limit. Oracle's SQL reference specifies a maximum of 512 bytes for the pattern used by REGEXP_LIKE. This limit applies to the pattern, rather than the text being searched. For more information, refer to Pattern-matching Conditions.

Sorting, Summarizing, and Merging Results

Sorting, summary operations, and duplicate merging have different purposes.

Sorting

Use < or > on a mapped search column to request ascending or descending order:

              {
  "id": "internalid",
  "label": "<title"
} 

            

This mapping orders the search by task title. Sorting does not increase the number of retrieved results.

For an article record model, article.sortby sorts the retrieved, mapped articles in ascending text order by a top-level property. For example, the standard History resource uses "sortby": "date" to order articles combined from its named sources. This sorting happens after retrieval and combination. It does not determine which rows NetSuite retrieves first. It is separate from the sort property used to order a resolved combined array and from any sorting applied by the FSM Mobile interface. Numbers are compared as text, so use a search-column sort where numeric ordering is required.

Summary Searches

Use ^ for a grouped column and a summary flag for each aggregated column. For example:

              {
  "record": "task",
  "filters": ["case.internalid", "noneof", "@NONE@"],
  "all": true,
  "map": {
    "caseId": "^case.internalid",
    "taskCount": "?internalid"
  }
} 

            

This search produces a count of matching tasks for each linked case. Its returned objects describe groups, rather than editable task records. Use compatible grouped or aggregated columns throughout a summary map. NetSuite determines which summary operations are valid for each column.

Use } for a maximum value and { for a minimum value. The ^ flag groups values. It does not select their maximum.

Merging Duplicate Rows

A joined search can return more than one row for a record. The * flag merges mapped objects with the same key after their search rows are read. For example, standard transaction maps use a merge key to collect lines into one transaction object.

Place the merge-key mapping first in the object and ensure that every row to keep has a populated key. Arrays are concatenated during merging. Existing populated individual values are retained, and missing values can be supplied by later rows. Duplicate merging is not a summary search and does not automatically remove duplicate entries from a merged array.

Use grouping and aggregation to calculate totals across search rows. Use duplicate merging when the result needs an object assembled from those rows.

Articles Built from Multiple Searches

An article definition without a direct record property can contain named source definitions. Each source has its own record, filters, and map. Supported search options such as all apply to that source. The standard History resource uses this structure to combine completed CRM Tasks and Project Tasks with related transaction and file data.

The standard record model combines those results by their mapped id. Sources describing the same article must use the same ID. Records that should remain separate must use distinct IDs. If a source map omits id, the model supplies an ID in the form <record type>-<internal ID>.

If two sources return the same article ID, properties from the second source replace matching properties from the first source. An array property is also replaced, rather than concatenated. Avoid relying on source order to resolve conflicting values across several sources. Give each combined property one source where possible. This combination is different from the * duplicate-row merge within an individual search and from the array: true option-list combination described in Combining Search Results. article.sortby can order the combined articles afterward.

Using Nested Searches

A search can supply values used by another search's filters. FSM resolves the inner search before executing the outer search. The inner map should return the value shape expected by the outer filter, such as an array of internal IDs.

The following example retrieves the case linked to the current CRM Task:

            {
  "record": "supportcase",
  "filters": [
    "internalid",
    "anyof",
    {
      "array": true,
      "default": "0",
      "linkedCaseIds": {
        "record": "task",
        "filters": [
          ["internalid", "anyof", "${event.internalid}"],
          "and",
          ["case.internalid", "noneof", "@NONE@"]
        ],
        "map": "case.internalid"
      }
    }
  ],
  "map": {
    "id": "internalid",
    "label": "casenumber"
  }
} 

          

The array: true object combines its supplied values into one array. The string "0" ensures that the filter value is not an empty array when no linked case is found. When the inner search returns a case ID, the combined array still includes "0" as well as that ID.

In this pattern, default is a name for an included value. It is not a conditional fallback: the value is included whether the inner search finds records. The name linkedCaseIds labels the inner search and is not a NetSuite field ID.

Choose an included placeholder appropriate to the filter. Do not substitute "@NONE@" for "0" without considering the operator and field: the empty-value marker can change which records match. An empty inner search does not otherwise supply a filter value automatically.

Where either search can return more than 1,000 rows, give that search its own all: true in a supported location. Setting all on the outer search does not enable it for the inner search.

Combining Search Results

An array: true object can combine several option searches. Each search should return the same option shape.

            {
  "array": true,
  "sort": "label",
  "serviceItems": {
    "record": "item",
    "filters": [
      ["isinactive", "is", "F"],
      "and",
      ["type", "anyof", "Service"]
    ],
    "all": true,
    "map": {
      "id": "internalid",
      "label": "itemid"
    }
  },
  "nonInventoryItems": {
    "record": "item",
    "filters": [
      ["isinactive", "is", "F"],
      "and",
      ["type", "anyof", "NonInvtPart"]
    ],
    "all": true,
    "map": {
      "id": "internalid",
      "label": "itemid"
    }
  }
} 

          

Use this object as an element's options definition. It combines the two lists and sorts their string labels without regard to letter case. Set sort to the name of the option property to sort by. Every included option must supply a suitable string value for that property.

Combining arrays does not deduplicate options. If the searches overlap, adjust their filters or otherwise ensure that duplicate choices are not returned.

For a list used on several tabs, define the search one time in a loaded supporting resource and reference its options. For the complete Inventory placement and loading relationship for the user resource, see Sharing Data Between Resources in FSM Configuration. That subsection also includes an example of a Select that uses the shared options. Referencing the loaded list does not run a separate search each time it is used.

Retrieving More Than 1,000 Results

Standard FSM search retrieval returns the first 1,000 search rows. In supported locations, all: true retrieves further batches of up to 1,000 rows until the search results are exhausted. It does not remove NetSuite execution or governance limits.

Search Location

all: true Behavior

Resolved element options or value search.

Passed to standard search retrieval.

Resolved nested search.

Passed for that individual search.

Resolved report or email data search within a notification definition.

Passed for that individual search.

An individual named search within a standard multi-source article definition.

Passed with that search's options.

A search defined directly on an article with its own record property.

The standard single-source article retrieval does not pass this property to the search.

For example, in the CRM Task options search in Defining a Search, all is alongside record, filters, and map. It is not a route-wide setting. In a collection of nested or named searches, set it separately on every supported search that needs more results.

Here, single-source means an article with a direct record property. It can display multiple records of that type. This definition does not mean that the resource displays only one record.

Search-row counts can differ from the number of final mapped objects. Joined rows can be merged, and summary searches return groups. Do not infer that all underlying data was retrieved solely from the number of visible records.

Retrieve only the records and columns needed for the behavior. Larger searches can increase load time, response size, and processing usage. If a direct article search needs to exceed the standard retrieval limit, resolve that design before relying on all in that location.

For guidance on measuring the effect of larger searches on loading time and response size, see FSM Performance and Data Collection.

Mapping Table Values to Sublists

A Table element defines FSM Mobile rows and their child elements. It does not by itself define how those rows are stored in a NetSuite sublist.

A sublist mapping uses an array of row mappings. The write side of each mapping identifies the sublist and field, such as expense.memo. The read side uses the valid search column or formula, which can have a different name.

For example, this fragment illustrates the memo and amount mappings used for expense report lines:

            {
  "expenses": [
    {
      "memo": "memo|expense.memo",
      "amount": "amount|expense.amount"
    }
  ]
} 

          

This example is a mapping fragment, rather than a complete expense report definition. A complete transaction resource also needs its record identity, line selection, duplicate-row merge mapping, required line fields, and applicable transaction behavior. Preserve the feature's standard transaction model and mappings when extending it.

The first string mapping in a row object identifies its sublist scope. Keep mappings within that row object consistent with the intended sublist. The [] multiselect flag is a different mechanism and does not supply sublist line mappings.

Warning:

Saving an array mapped to an entire sublist can remove existing lines that are absent from the supplied array. Do not use a filtered or incomplete line array as a complete editable sublist without accounting for the omitted lines.

Related Topics

General Notices