Hướng dẫn schema
Hướng dẫn schemaBài 20: Kết hợp dữ liệu người dùng từ nhiều nguồn

Bài 20: Kết hợp dữ liệu người dùng từ nhiều nguồn

Trong bài học hướng dẫn trước, chúng ta đã tìm hiểu rằng có thể lấy dữ liệu người dùng từ REST API của Mailchimp và kết hợp với dữ liệu người dùng được lưu trữ trên trang web của mình.

Chúng ta có thể tổng quát hóa ý tưởng này, áp dụng nó cho bất kỳ hai nguồn dữ liệu nào, kết hợp các tập dữ liệu của chúng thành một, rồi thực hiện một số thao tác với dữ liệu đã kết hợp.

Kết hợp các tập dữ liệu từ nhiều nguồn

Trường hàm _arrayInnerJoinJSONObjectProperties (được cung cấp bởi tiện ích mở rộng PHP Functions Via Schema) cho phép chúng ta kết hợp các đối tượng JSON tham chiếu đến cùng một thực thể thành một đối tượng JSON duy nhất chứa tất cả các thuộc tính.

Các đối tượng JSON ở cả hai nguồn có thể được xác định là tham chiếu đến cùng một thực thể vì thuộc tính "chỉ mục" của chúng có cùng giá trị.

Trong GraphQL query này, các đầu vào sourcetarget nhận các danh sách đối tượng JSON có chung thuộc tính email (và do đó được dùng làm "chỉ mục"):

query {
  _arrayInnerJoinJSONObjectProperties(
    source: [
      {
        email: "abracadabra@ganga.com",
        lang: "de"
      },
      {
        email: "longon@caramanon.com",
        lang: "es"
      },
      {
        email: "rancotanto@parabara.com",
        lang: "en"
      },
      {
        email: "quezarapadon@quebrulacha.net",
        lang: "fr"
      },
      {
        email: "test@test.com",
        lang: "de"
      },
      {
        email: "emilanga@pedrola.com",
        lang: "fr"
      }
    ],
    target: [
      {
        email: "quezarapadon@quebrulacha.net",
        name: "Abrigail Ataluncha"
      },
      {
        email: "abracadabra@ganga.com",
        name: "Chip Bennett"
      },
      {
        email: "contributor@test.com",
        name: "Contributor"
      },
      {
        email: "longon@caramanon.com",
        name: "Emil Uzelac"
      },
      {
        email: "rancotanto@parabara.com",
        name: "Lance Ampsrong"
      },
      {
        email: "leo@getpop.org",
        name: "leo"
      },
      {
        email: "test@test.com",
        name: "Test"
      },
      {
        email: "emilanga@pedrola.com",
        name: "Theme Demos"
      }
    ],
    index: "email"
  )
}

Khi giá trị thuộc tính email giống nhau trong các đối tượng JSON nguồn và đích, những đối tượng đó sẽ được kết hợp trong danh sách kết quả:

{
  "data": {
    "_arrayInnerJoinJSONObjectProperties": [
      {
        "email": "quezarapadon@quebrulacha.net",
        "name": "Abrigail Ataluncha",
        "lang": "fr"
      },
      {
        "email": "abracadabra@ganga.com",
        "name": "Chip Bennett",
        "lang": "de"
      },
      {
        "email": "contributor@test.com",
        "name": "Contributor"
      },
      {
        "email": "longon@caramanon.com",
        "name": "Emil Uzelac",
        "lang": "es"
      },
      {
        "email": "rancotanto@parabara.com",
        "name": "Lance Ampsrong",
        "lang": "en"
      },
      {
        "email": "leo@getpop.org",
        "name": "leo"
      },
      {
        "email": "test@test.com",
        "name": "Test",
        "lang": "de"
      },
      {
        "email": "emilanga@pedrola.com",
        "name": "Theme Demos",
        "lang": "fr"
      }
    ]
  }
}

Chúng ta có thể lấy dữ liệu được lưu trữ trong nhiều dịch vụ đám mây (có thể truy cập thông qua API của các dịch vụ đó) và kết hợp các tập dữ liệu rời rạc này lại với nhau.

Chẳng hạn, hãy chọn bất kỳ hai dịch vụ nào trong số các dịch vụ có thể lưu trữ dữ liệu người dùng sau đây:

  • Mailchimp
  • Dropbox
  • GitHub
  • Microsoft Teams
  • Slack
  • Trello
  • Google Drive
  • Trang web WordPress của bạn
  • Các ứng dụng nội bộ của công ty bạn
  • v.v.

GraphQL query dưới đây kết hợp các tập dữ liệu từ hai dịch vụ giả định:

  1. Một hệ thống newsletter (lưu trữ dữ liệu người đăng ký, bao gồm email và ngôn ngữ họ sử dụng)
  2. Một CRM (lưu trữ dữ liệu khách hàng, bao gồm tên và email)

Đầu tiên, nó lấy tất cả bản ghi từ dịch vụ newsletter và trích xuất các địa chỉ email. Sau đó, nó dùng các email này để tạo URL endpoint cho REST API của CRM, nhằm chỉ lấy dữ liệu của những người dùng đó. Cuối cùng, nó kết hợp cả hai tập dữ liệu thành một, xoay quanh thuộc tính chung email:

query ProvideNewsletterUserData {
  userList: _sendJSONObjectCollectionHTTPRequest(
    input: {
      url: "https://newapi.getpop.org/wp-json/newsletter/v1/subscriptions"
    }
  )
    @export(as: "userList")
 
  userEmails: _echo(value: $__userList)
    @underEachArrayItem(passValueOnwardsAs: "userListItemForEmail")
      @applyField(
        name: "_objectProperty",
        arguments: {
          object: $userListItemForEmail,
          by: {
            key: "email"
          }
        },
        setResultInResponse: true
      )
    @export(as: "userEmails")
}
 
query CombineUserDataFromDisparateSources
  @depends(on: "ProvideNewsletterUserData")
{
  joinedUserEmails: _arrayJoin(
    array: $userEmails,
    separator: "&emails[]="
  )
 
  userEndpoint: _strAppend(
    after: "https://newapi.getpop.org/users/api/rest/?query={name%20email}&emails[]=",
    append: $__joinedUserEmails
  )
 
  userEndpointDataItems: _sendJSONObjectCollectionHTTPRequest(
    input: {
      url: $__userEndpoint
    }
  )
 
  userData: _arrayInnerJoinJSONObjectProperties(
    source: $__userEndpointDataItems,
    target: $userList,
    index: "email"
  )
    @export(as: "userData")
}

...cho kết quả:

{
  "data": {
    "userList": [
      {
        "email": "abracadabra@ganga.com",
        "lang": "de"
      },
      {
        "email": "longon@caramanon.com",
        "lang": "es"
      },
      {
        "email": "rancotanto@parabara.com",
        "lang": "en"
      },
      {
        "email": "quezarapadon@quebrulacha.net",
        "lang": "fr"
      },
      {
        "email": "test@test.com",
        "lang": "de"
      },
      {
        "email": "emilanga@pedrola.com",
        "lang": "fr"
      }
    ],
    "userEmails": [
      "abracadabra@ganga.com",
      "longon@caramanon.com",
      "rancotanto@parabara.com",
      "quezarapadon@quebrulacha.net",
      "test@test.com",
      "emilanga@pedrola.com"
    ],
    "joinedUserEmails": "abracadabra@ganga.com&emails[]=longon@caramanon.com&emails[]=rancotanto@parabara.com&emails[]=quezarapadon@quebrulacha.net&emails[]=test@test.com&emails[]=emilanga@pedrola.com",
    "userEndpoint": "https://newapi.getpop.org/users/api/rest/?query={name%20email}&emails[]=abracadabra@ganga.com&emails[]=longon@caramanon.com&emails[]=rancotanto@parabara.com&emails[]=quezarapadon@quebrulacha.net&emails[]=test@test.com&emails[]=emilanga@pedrola.com",
    "userEndpointDataItems": [
      {
        "name": "Abrigail Ataluncha",
        "email": "quezarapadon@quebrulacha.net"
      },
      {
        "name": "Chip Bennett",
        "email": "abracadabra@ganga.com"
      },
      {
        "name": "Contributor",
        "email": "contributor@test.com"
      },
      {
        "name": "Emil Uzelac",
        "email": "longon@caramanon.com"
      },
      {
        "name": "Lance Ampsrong",
        "email": "rancotanto@parabara.com"
      },
      {
        "name": "leo",
        "email": "leo@getpop.org"
      },
      {
        "name": "Test",
        "email": "test@test.com"
      },
      {
        "name": "Theme Demos",
        "email": "emilanga@pedrola.com"
      }
    ],
    "userData": [
      {
        "email": "abracadabra@ganga.com",
        "lang": "de",
        "name": "Chip Bennett"
      },
      {
        "email": "longon@caramanon.com",
        "lang": "es",
        "name": "Emil Uzelac"
      },
      {
        "email": "rancotanto@parabara.com",
        "lang": "en",
        "name": "Lance Ampsrong"
      },
      {
        "email": "quezarapadon@quebrulacha.net",
        "lang": "fr",
        "name": "Abrigail Ataluncha"
      },
      {
        "email": "test@test.com",
        "lang": "de",
        "name": "Test"
      },
      {
        "email": "emilanga@pedrola.com",
        "lang": "fr",
        "name": "Theme Demos"
      }
    ]
  }
}