סינון תחביר

בשיטות מסוימות של list ב-Merchant API, כמו account.list, אתם יכולים לסנן את התוצאות כדי לקבל רק את התוצאות שמעניינות אתכם. כדי לסנן תוצאות, משתמשים בפרמטר filter עם התחביר שמוגדר בדקדוק EBNF. בדף הזה מוסבר איך להשתמש בתחביר כדי לסנן חשבונות.

תחביר

כל הערכים שאינם מספרים שלמים חייבים להיות מוקפים במירכאות כפולות ("). כדי לדעת אילו ערכים שדה מסוים מקבל, עיינו במאמרי העזרה של אותו שדה.

אפשר להשתמש ב-AND כדי לסנן לפי כמה שדות באותה שאילתה. אפשר גם להשתמש ב-AND כדי לשלב כמה מסננים של relationship(...) ו-service(...). הנה דוגמה שמשלבת כמה מסננים של relationship(...) ו-service(...):

(relationship(service(type = "ACCOUNT_MANAGEMENT") AND service(handshakeState = "PENDING"))) OR (accountName = "store" AND relationship(...))

הדוגמה הזו מחזירה את החשבונות הבאים:

  • כל החשבונות שיש להם קשר של ניהול חשבון עם חשבון אחר, וקשר נוסף שממתין לאישור.

  • כל החשבונות עם השם המוצג "store", שיש להם קשרים לחשבונות אחרים.

אי אפשר להשתמש ב-AND כדי לסנן לפי כמה ערכים באותו שדה. לדוגמה, אי אפשר להשתמש ב-accountName = "*A*" AND accountName = "*B*".

אפשר להשתמש ב-OR כדי לסנן לפי שני שדות באותה שאילתה. תוחמים בסוגריים את הקריטריונים לסינון בכל אחד מהצדדים של האופרטור OR. לדוגמה: (accountName = "storeA") OR (accountName = "storeB").

אפשר להשתמש רק ב-OR כדי לשלב בין שני שדות. לדוגמה, אי אפשר להשתמש ב-(accountName = "storeA") OR (accountName = "storeB") OR (accountName = "storeC").

אי אפשר להשתמש בסוגריים, חוץ מאשר עם האופרטורים AND ו-OR, ובקריאות לפונקציות, כמו relationship(...) ו-service(...).

בשדות של מחרוזות כמו accountName ו-accountIdAlias, אפשר לסנן לפי ערכים שמכילים מילה או רצף תווים מסוימים, על ידי הוספת כוכביות (*) לפני ואחרי הרצף. לדוגמה, השאילתה accountName = "*foo*" מחזירה את כל החשבונות שבהם השדה accountName מכיל את הערך foo, כמו "storeFoo".

כדי לסנן ערכים שלא מכילים רצף מסוים, אפשר להשתמש ב-!= וב-*. לדוגמה, accountName != "*foo*" מחזיר את כל החשבונות עם accountName שלא מכיל את foo.

המערכת מתעלמת מרווחים מיותרים. לדוגמה, foo AND bar זהה ל-foo AND bar.

ריכזנו כאן כמה דוגמאות לסינון חשבונות באמצעות השיטה account.list:

  • כל החשבונות המשניים של חשבון מתקדם שמכילים את המילה "חנות":
accountName = "*store*" AND relationship(service(type = "ACCOUNT_AGGREGATION"))
  • כל החשבונות שמנוהלים על ידי ספק 123456:
relationship(service(type = "ACCOUNT_MANAGEMENT") AND providerId = 123456)
  • כל החשבונות ששלחו הזמנה לספק 123456 או שצריכים לאשר הזמנה מהספק הזה:
relationship(service(handshakeState = "PENDING" AND type ="ACCOUNT_MANAGEMENT")
AND providerId = 123456)

כדי לסנן את החשבונות שלמשתמש ששולח את הבקשה יש גישה אליהם, משתמשים ב-method‏ google.shopping.merchant.accounts.v1.ListAccountsRequest, כמו שמוצג בדוגמה הבאה.

Java

import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.shopping.merchant.accounts.v1.Account;
import com.google.shopping.merchant.accounts.v1.AccountsServiceClient;
import com.google.shopping.merchant.accounts.v1.AccountsServiceClient.ListAccountsPagedResponse;
import com.google.shopping.merchant.accounts.v1.AccountsServiceSettings;
import com.google.shopping.merchant.accounts.v1.ListAccountsRequest;
import shopping.merchant.samples.utils.Authenticator;
import shopping.merchant.samples.utils.Config;

/** This class demonstrates how to filter the accounts the user making the request has access to. */
public class FilterAccountsSample {

  public static void filterAccounts(Config config) throws Exception {

    // Obtains OAuth token based on the user's configuration.
    GoogleCredentials credential = new Authenticator().authenticate();

    // Creates service settings using the credentials retrieved above.
    AccountsServiceSettings accountsServiceSettings =
        AccountsServiceSettings.newBuilder()
            .setCredentialsProvider(FixedCredentialsProvider.create(credential))
            .build();

    // Calls the API and catches and prints any network failures/errors.
    try (AccountsServiceClient accountsServiceClient =
        AccountsServiceClient.create(accountsServiceSettings)) {

      // Filter for accounts with display names containing "store" and a provider with the ID "123":
      String filter = "accountName = \"*store*\" AND relationship(providerId = 123)";

      // Filter for all subaccounts of account "123":
      // String filter2 = "relationship(providerId = 123 AND service(type =
      // \"ACCOUNT_AGGREGATION\"))";

      // String filter3 = "relationship(service(handshakeState = \"APPROVED\" AND type =
      // \"ACCOUNT_MANAGEMENT\") AND providerId = 123)";

      ListAccountsRequest request = ListAccountsRequest.newBuilder().setFilter(filter).build();

      System.out.println("Sending list accounts request with filter:");
      ListAccountsPagedResponse response = accountsServiceClient.listAccounts(request);

      int count = 0;

      // Iterates over all rows in all pages and prints the sub-account
      // in each row.
      // `response.iterateAll()` automatically uses the `nextPageToken` and recalls the
      // request to fetch all pages of data.
      for (Account account : response.iterateAll()) {
        System.out.println(account);
        count++;
      }
      System.out.print("The following count of elements were returned: ");
      System.out.println(count);
    } catch (Exception e) {
      System.out.println(e);
    }
  }

  public static void main(String[] args) throws Exception {
    Config config = Config.load();

    filterAccounts(config);
  }
}

מפרט

המסננים פועלים לפי קבוצת משנה של מפרט מסנן AIP, והדקדוק הפורמלי של EBNF:

filter
    : accountFilterDisj
    | accountFilterConj

accountFilterDisj
    : "(" accountFilterConj " OR " accountFilterConj ")"
    ;
accountFilterConj
    : accountFilter {" AND " accountFilter}
    ;

accountFilter
    : accountNameFilter | capabilityFilter | relationshipFn | accessFilter
    ;

accountNameFilter
    : "accountName" comparator value
    ;

capabilityFilter
    : "capabilities:" capabilityValue
    | "-capabilities:" capabilityValue
    | "NOT capabilities:" capabilityValue
    ;
capabilityValue
    : "CAN_UPLOAD_PRODUCTS"
    ;

accessFilter
    : "access = " accessType
    ;

accessType
    : "DIRECT"
    | "INDIRECT"
    | "ALL"
    ;

relationshipFn
    : "relationship(" relationshipConj ")"
    ;
relationshipConj
    : relationshipFilter {" AND " relationshipFilter}
    ;
relationshipFilter
    : "providerId = " numValue
    | "accountIdAlias" comparator value
    | serviceFn
    ;

serviceFn
    : "service(" serviceConj ")"
    ;
serviceConj
    : serviceFilter {" AND " serviceFilter}
    ;
serviceFilter
    : "externalAccountId" comparator value
    | "handshakeState = " handshakeState
    | "type = " serviceType
    ;

handshakeState
    : "PENDING"
    | "WAITING"
    | "ESTABLISHED"
    | "REJECTED"
    ;
serviceType
    : "ACCOUNT_AGGREGATION"
    | "ACCOUNT_MANAGEMENT"
    ;

comparator
    : " = "
    | " != "
    ;