vte.cx 및 BigQuery 통합
0. BigQuery 준비
서비스 계정은 Google의 서비스 권한이 있는 계정입니다.Google 서비스에 대한 API 요청 시 인증 정보로 사용됩니다.
1. vte.cx측의 협업 설정
{
"type": "XXX",
"project_id": "XXX",
"private_key_id": "XXX",
"private_key": "XXX",
"client_email": "XXX",
"client_id": "XXX",
"auth_uri": "XXX",
"token_uri": "XXX",
"auth_provider_x509_cert_url": "XXX",
"client_x509_cert_url": "XXX"
}
properties.xml
rights
항목에 3줄 추가_bigquery.projectid={プロジェクトID}
_bigquery.dataset={データセット名}
_bigquery.location=asia-northeast1
npm run upload
등록!
처음 등록할 때 vte입니다.cx측의 모드 항목과
key (STRING)
, updated (DATETIME)
, deleted (BOOL)
, postBQ(request: any, async: boolean, tablenames?: any): void
항목을 가진 표를 만듭니다.request
API의 설명
request:
template.xml 발췌문
<content>foo
bar(string)
baz(string)</content>
link
↓ 상단 모드 대응[
{
foo: { bar: 'test', baz: 'テスト' },
link: [{ ___rel: 'self', ___href: 'エントリごとに一意' }]
}
]
___rel: 'self'
의___href
,'/{エンドポイントのキー名}/{採番処理で振られたID番号}'
는 보통___href
key
의 값은 { '第一階層の項目名' : 'テーブル名' }
항목으로 BigQuery 테이블에 등록됩니다.async:_
지정
getBQ(sql: string, parent?: string): any
을 통해 다른 표에 등록할 수 있습니다.위 모드에서의 실현 예시
/src/server/registerBQ.ts
import * as vtecxapi from 'vtecxapi'
const KEY = 'somefoo'
const END_POINT = '/d/' + KEY
const PARENT = 'foo'
const TABLE = 'footable' // 'リクエストはこのテーブルに登録される'
const [{ foo }] = vtecxapi.getRequest()
const id = vtecxapi.allocids(END_POINT, 1) //採番
const request = [
{ [PARENT]: { ...foo, id }, link: [{ ___href: `/${KEY}/${id}`, ___rel: 'self' }] }
]
const result = vtecxapi.postBQ(request, false, { [PARENT]: TABLE }) // 冗長に引数tablenamesを記述した例
vtecxapi.doResponse({ feed: { title: result } }) // ATOM形式のレスポンスのtitle項目に結果を持たせる
↑ 파일/src/components/register.ts
const foo = { bar: 'test', baz: 'テスト' }
axios.put('/s/registerBQ', [{ foo }] ) // 通例としてPOSTよりPUTを使う
얻다
key
실행 결과는parent의 하위 요소입니다.항목 내에서 모드 또는 ATOM 항목에 없는 항목을 지정하는 중 오류 발생SQL 실행 및 체크 아웃된 데이터 반환
데이터 업데이트 없이 항상 추적되므로 동일한
updated
의 최신 및 deleted=false
SQL 가져오기설치 예
/src/server/readBQ.ts
import * as vtecxapi from 'vtecxapi'
const DATASET = '{BigQueryの該当データセット名}'
const TABLE = '{BigQueryの該当テーブル名}'
const SCHEMA = {userid:'ID',name:'名前',gender:'性別',age:'年齢',birth:'生年月日',email:'メールアドレス',tel:'電話番号',postcode:'郵便番号',address:'住所',memo:'備考欄'}
// あらかじめ用意したテーブルから作成
const ITEMS = Object.keys(SCHEMA)
const TITLES = Object.values(SCHEMA)
const ORDER = 'order by f.userid asc'
const sql = `
select
${ITEMS.join(',') /* =>'useid,name,...,memo' */}
from
${DATASET}.${TABLE} as f
right join
( select
key,
max(updated) as updated
from
${DATASET}.${TABLE}
group by
key
) as k
on
f.updated = k.updated and
f.key = k.key
where
f.deleted = false
${ORDER}
`
const result = vtecxapi.getBQ(sql, PARENT) // 冗長に引数parentを指定した例
vtecxapi.doResponse(result)
/src/components/read.ts const read = async () => await axios.get('/s/readBQ')
편집자
편집된 데이터
key
에서 무단으로 재등록합니다.삭제
postBQ
-파라미터request
의link
의___href
를 항목으로 표에 등록한다.key
→매개 변수deleteBQ
에 표에 추가된 keys: string[]
항목→ 등록
key
인 레코드deleted
keys: true
async:_tablenames:
deleteBQ(keys: string[], async: boolean, tablenames?:any): void
→ 다른 표에서 삭제설치 예
/src/components/delete.tsx
// userエントリの形 { userid: 1 , name: 太郎, ... }
const keys = [user1, user2, ...].map(({ userid }) => userid)
const delete = async () => await axios.put('/s/deleteBQ', keys)
/src/server/deleteBQ.tsconst _keys = vtecxapi.getRequest()
const keys = _keys.map(id => `/${TABLE}/${id}`)
vtecxapi.deleteBQ(keys, false, { [PARENT]: TABLE })
전체 수량 획득
getTotal.ts
// vtecxapi.getQueryString(param:string)で検索条件など取得できる
const sql =`
select
cast(count(*) as string) as title
from
${DATASET}.${TABLE} as f
right join
( select
key,
max(updated) as updated
from
${DATASET}.${TABLE}
group by
key
) as k
on
f.updated = k.updated and
f.key = k.key
where
f.deleted = false
${/*検索条件など*/}
`
const total = getBQ(sql) // =>[ { 'title': '合計件数' } ] ←SQLクエリの'as title'によって結果が'title'に入る
vtecxapi.doResponse(total) // レスポンスに入れるエントリにはATOM項目とユーザー定義スキーマの項目のみを入れられる
페이지 및 검색을 수행하는 SQL 예
link의 href 항목 문장의 페이지 문자와 검색 기능 사용하기
/src/server/getUsers.ts
import * as vtecxapi from 'vtecxapi'
import { escape } from 'sqlstring'
const DATASET = 'データセット名'
const TABLE = 'テーブル名'
// テーブルから取得する項目
const ITEMS = [ 'name', 'userid', 'gender', 'birth', 'age', 'tel', 'email', 'address', 'postcode', 'memo']
// SQLクエリを組み立てる
// 検索のためのクエリ
// クエリパラメータ'search'から'name'項目の検索キーワードを設定
const search = encodeURIComponent(vtecxapi.getQueryString('search'))
const name_search = search ? ` and name = "${escape(search)}"` : ''
// ページネーションのためのクエリ
// クエリパラメータ'page'からページを設定
const page_num = Number(encodeURIComponent(vtecxapi.getQueryString('page'))) || 1
const pagination = `limit 5 offset ${escape(page_num - 1)}` // 5件ずつ
const conditions = `${name_search} order by f.userid desc ${pagination}`
const total = vtecxapi.getBQ(sql_total) // =>[ { 'title': '合計数' } ] sql文で'as title'としているため。
// ページネーションのためにフィードを数件ごとに取得
const sql_feed = `
select
${ITEMS.join(',')}
from
${DATASET}.${TABLE} as f
right join
( select
key,
max(updated) as updated
from
${DATASET}.${TABLE}
group by
key
) as k
on
f.updated = k.updated and
f.key = k.key
where
f.deleted = false
${conditions}
`
// 'select userid,name,gender,age,email,tel,postcode,address,memo, from ${DATASET}.${TABLE} as f right join (select key,max(updated) as updated from ${DATASET}.${TABLE} group by key) as k on f.updated=k.updated and f.key=k.key where f.deleted=false'
const result = vtecxapi.getBQ(sql_feed, PARENT)
vtecxapi.doResponse(result) // =>[ { 'user': { 'userid': '1', 'name': '太郎', ... } }, ... ]
{ '第一階層の項目名' : 'テーブル名' }
, OFFSET
를 사용하는 페이지 판식을 편이 방식이라고 한다.키를 사용하여 설정된 페이지 스타일
각 행
LIMIT
에서 테이블에서 추출한 고유OFFSET
항목(→ 키 세트)을 사용하여 아무 페이지나 id
의 데이터를 가져오는 SQL 발행클라이언트
URL 쿼리 매개 변수
LENGTH
(가정)에서 페이지 번호의 바닥글 가져오기src/hooks/usePage.tsx
import { useLocation } from 'react-router-dom'
export const usePage = () => {
const _search_params = useLocation().search
const search_params = new URLSearchParams(_search_params)
const page = Number(query.get('page')) || 1
return page
}
페이지 인터럽트에 사용할 키 집합을 요청하고, 이 키 집합과 갈고리를 통해 요청한 페이지 번호 피드를 사용합니다/src/components/getUsers.tsx
import { usePage } from '../hooks/usePage'
const shouldUpdateKeyset = useRef(true)
const Users = () => {
const [keyset, setKeyset] = useState([])
const page = usePage()
const [feed, setFeed] = useState([])
const getFeed = () => {
if (shouldUpdateKeyset.current) {
const _keyset = async () => await axios.get('/s/getKeyset')
// =>[ { title: '11', subtitle: '1' }, { title: '5', subtitle: '2' }, { title: '1', subtitle: '3' } ]
// (データが15個ある場合), 'title'に`userid`、`subtitle`にページ番号
setKeyset(_keyset.data.map(({title})=>title))
shouldUpdateKeyset.current = false
}
if (keyset.hasOwnProperty(page-1)) {
const _feed = await axios.get(`/s/getUsers?pagekey=${keyset[page-1]?.title}`)
setFeed(_feed)
}
}
useEffect(getFeed,[])
return // feedを描写
}
서버측import * as vtecxapi from 'vtecxapi'
const DATASET = 'データセット'
const TABLE = 'テーブル'
const LENGTH = 5
const ORDER = 'order by userid desc'
const keyset = getBQ(`
with x as (
select
case
mod(
row_number()
over(
${ORDER}
),
${LENGTH}
)
when 0
then 1
else 0
end as page_boundary,
f.*
from
${DATASET}.${TABLE} as f
right join (
select
key,
max(updated) as updated
from
${DATASET}.${TABLE}
group by
key
) as k
on
f.updated = k.updated and
f.key = k.key
where
f.deleted = false
${ORDER}
)
select
userid as title,
cast (
row_number()
over(
${ORDER}
) + 1
as string
) as subtitle
from
x
where
x.page_boundary = 1
`)
vtecxapi.doResponse(keyset)
/src/server/getUsers.ts
import * as vtecxapi from 'vtecxapi'
import { escape } from 'sqlstring'
const DATASET = 'データセット'
const TABLE = 'テーブル'
const LENGTH = 5
const pagekey = escape(vtecxapi.getQueryString('pagekey')) || 0
const ITEMS = [ 'name', 'userid', 'gender', 'birth', 'age', 'tel', 'email', 'address', 'postcode', 'memo']
const feed = vtecxapi.getBQ(`
select
${ITEMS.join(',') /* =>'useid,name,...,memo' */}
from
${DATASET}.${TABLE} as f
right join (
select
key,
max(updated) as updated
from
${DATASET}.${TABLE}
group by
key
) as k
on
f.updated = k.updated and
f.key = k.key
where
f.deleted = false and
userid >= ${pagekey/*'userid'がページキーである'userid'と等しいか、それより小さい行を'LENGTH'分だけ抽出*/}
${ORDER/*'userid'降順*/}
limit ${LENGTH}
`)
+ 필요에 따라 총 데이터 수, 필터 결과(→ 검색 기능) 등 획득
Reference
이 문제에 관하여(vte.cx 및 BigQuery 통합), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/sugimotohiro/articles/vtecx_server_bq텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)