Boxのメタデータクエリの使用

Yuko Taniguchi
Box Developer Japan Blog
17 min readMar 28, 2023

--

メタデータでデータを明確にする

Boxメタデータとは、キーと値のペアとして格納される、コンテンツに関連付けられたカスタムデータです。これにより、コンテンツのコンテキストを示すことができます。メタデータクエリを使用すると、コンテンツに追加されたメタデータのコンテキストを検索することで、コンテンツを見つけることができます。これは非常に効果的で、ユーザーまたはサービスが必要なものを見つけるのに役立ちます。

この記事では、Box CLIREST APIPython SDKを使用したメタデータクエリについて説明します。

また、この記事は、前回のBoxとFastAPIを使用したメタデータサービスの構築にも触れています。前回の記事では、メディアファイルのメタデータを自動的に入力するためのFastAPIサービスを作成しました。

メタデータクエリの形式

Boxでメタデータクエリを使用できるようにするには、フィルタの条件に使用する属性を含むメタデータテンプレートのスコープとキーを把握する必要があります。また、ルートとなる開始フォルダも必要です。

さらに、検索のパラメータとそのパラメータの値を定義するクエリも必要です。

最後に、並べ替えとコンテンツの戻り値の属性を指定します。

必要に応じて、他のユーザーの代理として、そのユーザーのセキュリティコンテキストでメタデータの検索をシミュレーションすることもできます。

すべての例で、以下に留意してください。

  • スコープ: enterprise_877840855
  • キー: demoMediaMetadata
  • ルートフォルダ: 0
  • フィルタをかける属性: duration
  • 属性のキー: enterprise_877840855.demoMediaTemplate.duration
  • 代理が設定されるユーザー: 18622116055

CLIは、主に管理者が使用しますが、開発者が簡単なテストを行う場合も非常に便利です。この例では特に、CLIを使用して、ユーザーやテンプレートを確認するほか、アプリでコンテンツにアクセスできるかどうかも確認します。

CLIの使用

まず、JWT認証を使用するようbox-cliを構成します。ここでは、この認証に関連付けられたサービスユーザーのほか、コンテンツを所有するユーザーも設定されています。

自分の情報を取得します。

❯ box users:get --csv --fields type,id,name
# output
type,id,name
user,20130487697,JWT

サービスユーザーが私のコンテンツにアクセスできるよう、代理が設定されるユーザーは私にします。

❯ box users --csv --fields type,id,name
# output
type,id,name
user,18622116055,Rui Barbosa
...

メタデータを含むコンテンツは複数のフォルダ (19244297050019244166451) に存在しているため、コンテンツのリストを取得できるかどうか簡単に確認しましょう。

❯ box folders:items 192442970500 \
--as-user 18622116055 \
--csv --fields type,id,name
# output
type,id,name
file,1121082178302,BigBuckBunny.mp4
file,1127033253925,file_example_AVI_1280_1_5MG.avi
...
❯ box folders:items 192444166451 \
--as-user 18622116055 \
--csv --fields type,id,name
# output
type,id,name
file,1127036724403,file_example_MP3_1MG.mp3
file,1127032879396,file_example_MP3_2MG.mp3
...

メタデータクエリを操作するには、テンプレートのスコープとキーを把握している必要があります。ここでは、Demo Media Metadata (enterprise_877840855 demoMediaMetadata) を使用します。

❯ box metadata-templates \
--csv --fields id,type,templateKey,scope,displayName
# output
type,id,templateKey,scope,displayName
.,.,demoMediaMetadata,enterprise_877840855,Demo Media Metadata
...

それでは、時間が1~30秒のメディアファイルを探してみましょう。時間を表すメタデータフィールドがミリ秒で表わされていることに注意してください。

❯ box metadata-query enterprise_877840855.demoMediaMetadata 0 \
--as-user 18622116055 \
--query "duration >= :min AND duration <= :max" \
--query-params min=1000f,max=30000f \
--order-by duration=ASC \
--extra-fields type,id,name,metadata.enterprise_877840855.demoMediaMetadata.duration \
--csv --fields type,id,name,metadata.enterprise_877840855.demoMediaMetadata.duration
# output
type,id,name,metadata.enterprise_877840855.demoMediaMetadata.duration
file,1127036724403,file_example_MP3_1MG.mp3,27167
file,1127036652230,file_example_MP3_700KB.mp3,27252
file,1127033373615,file_example_WAV_5MG.wav,29628

上記のCLIコマンドの詳細を以下に示します。

# search for content using the demo media template (scope.key)
# starting from the root folder (0)
box metadata-query enterprise_877840855.demoMediaMetadata 0 \

# impersonating a user
--as-user 18622116055 \

# query the duration with 2 parameters (:min and :max)
--query "duration >= :min AND duration <= :max" \

# set :min to 1000 miliseconds and max to 30000ms
--query-params min=1000f,max=30000f \

#sort the output by duration
--order-by duration=ASC \

# include these extra fields
--extra-fields type,id,name,metadata.enterprise_877840855.demoMediaMetadata.duration \

# set the output to csv and show only these fields
--csv --fields type,id,name,metadata.enterprise_877840855.demoMediaMetadata.duration

box metadata-queryについては、こちらのCLIに関するドキュメントをご確認ください。

REST APIの使用

これをテストする最も簡単な方法は、Postmanを使用することです。最初にBox APIコレクションをフォークする方法をご確認ください。

1つ目の方法では、メタデータフィルタのURLパラメータを使用して、searchエンドポイントでGETを実行します。

メタデータパラメータを作成して、エンドポイントで使用します。

[
{
"scope":"enterprise_877840855",
"templateKey":"demoMediaMetadata",
"filters":{
"duration":{
"gt":1000,
"lt":30000
}
}
}
]
https://{{api.box.com}}/2.0/search
?mdfilters=[{"scope":"enterprise_877840855","templateKey":"demoMediaMetadata","filters":{"duration":{"gt":1000,"lt":30000}}}]
&fields=type,id,name,metadata.enterprise_877840855.demoMediaMetadata.duration

結果は次のとおりです。

Postmanを使用した場合のAPI呼び出しの出力

もう1つの方法では、メタデータクエリを使用して、execute readエンドポイントでPOSTを送信します。

POSTの本文は次のようになります。

{
"from": "enterprise_877840855.demoMediaMetadata",
"query": "duration >= :min AND duration <= :max",
"query_params": {
"min": 1000,
"max":30000
},
"ancestor_folder_id": "0",
"order_by": [
{
"field_key": "duration",
"direction": "asc"
}
],
"fields": [
"type",
"id",
"name",
"metadata.enterprise_877840855.demoMediaMetadata.duration"
]
}

結果は次のとおりです。

Postmanを使用した場合のAPI呼び出しの出力

検索およびメタデータクエリに関するAPIリファレンスをご確認ください。

Python SDKの使用

最初に、基本的な構成クラスと、ユーザーの代理を務めるBoxクライアントを返すget_box_client() メソッドを記述します。

"""sample script for box metadata query"""
from boxsdk import Client, JWTAuth
from boxsdk.object.search import MetadataSearchFilter, MetadataSearchFilters

# configuration class
class Config:
"""configurations"""
SCOPE = "enterprise_877840855"
KEY = "demoMediaMetadata"
ATTRIBUTE = "duration"
AS_USER = "18622116055"
JWT_FILE = ".jwt.config.json"

def get_box_client() -> Client:
"""returns a box client impersonating the user"""
cfg = Config()
auth = JWTAuth.from_settings_file(cfg.JWT_FILE)
service_client = Client(auth)
as_user = service_client.user(user_id=cfg.AS_USER)
return service_client.as_user(as_user)

メタデータに対してクエリを実行する1つの方法として、MetadataSearchFilters() による検索を使用し、その後、それをmetadata_filter引数としてclient.search().query() メソッドに渡します。

def main():
"""main function"""
cfg = Config()

# get a client inpersonating the user
client = get_box_client()

# initialize the metadata search class
mt_query = MetadataSearchFilters()

# create a metadata search filter for the specific template
mt_filter = MetadataSearchFilter(template_key=cfg.KEY, scope=cfg.SCOPE)

# add a range filter for the attribute
mt_filter.add_range_filter(field_key=cfg.ATTRIBUTE, gt_value=1000, lt_value=30000)

# add the filter to the query
mt_query.add_filter(mt_filter)

# search for items
items = client.search().query(None, limit=100, offset=0, metadata_filters=mt_query)

#### code removed for simplicity ###

結果は次のとおりです。

----------------------------------------------------------------------
type id name duration
----------------------------------------------------------------------
file 1127033373615 file_example_WAV_5MG.wav 29628
file 1127036652230 file_example_MP3_700KB.mp3 27252
file 1127036724403 file_example_MP3_1MG.mp3 27167

もう1つの方法として、検索のmetadata_query() メソッドを使用します。今回は、時間が100~600秒のファイルを探します。

def main():
"""main function"""
cfg = Config()

# get a client inpersonating the user
client = get_box_client()

# create a query using parameters
md_query = "duration >= :min AND duration <= :max"

# set the parameter values
md_params = {"min": 100000, "max": 600000}

# set the order by
order_by = [{"field_key": "duration", "direction": "ASC"}]

# set the fields to return
fields = [
"type",
"id",
"name",
"metadata." + cfg.SCOPE + "." + cfg.KEY + "." + cfg.ATTRIBUTE,
]

# search for items
mt_items = client.search().metadata_query(
from_template=cfg.SCOPE + "." + cfg.KEY,
ancestor_folder_id=0, # root folder
query=md_query,
query_params=md_params,
order_by=order_by,
fields=fields,
)

結果は次のとおりです。

----------------------------------------------------------------------
type id name duration
----------------------------------------------------------------------
file 1127038082548 file_example_MP3_5MG.mp3 132205
file 1121082178302 BigBuckBunny.mp4 596473

この実践的なスクリプトの完全版は、こちらのGitHub Gistからダウンロードできます。

Python SDKの検索に関するドキュメントをご確認ください。

Boxのその他のSDK (Java.NETNode) も同様の方法で動作しますので、ご確認ください。

Boxアプリ

ユーザーも、メタデータを使用して検索を実行できます。たとえば、次のように検索できます。

box.comアプリでのメタデータクエリの使用

メタデータクエリAPIと検索APIの比較

メタデータクエリAPIは検索APIを補完するものです。これを使用すると、カスタムメタデータに格納されている値に厳密に基づいてコンテンツを検索できるほか、インデックスの作成が遅延することなくメタデータの作成、更新、即時削除が即座に反映された結果を取得できます。

一方、検索APIは、あいまい一致が必要なときに使用します。結果は、ドキュメントのテキストやBoxのデフォルト属性に基づいて表示されます。これを使用すると、ファイル名やフォルダ名、対応するドキュメントのテキストで検索できるほか、シンプルなブール検索 (“属性” = “値” など) を使用して条件に基づいて結果にフィルタをかけることができます。

検索APIは、インデックス作成 (コンテンツをアップロードまたは変更するたびに発生するプロセス) に依存しており、インデックス作成の遅延やフィルタの限定的な運用などの制約があります。

ドキュメントのコンテンツではなくメタデータに厳密に基づいてコンテンツを検索する場合は、メタデータクエリAPIを使用する必要があります。

一般的に、メタデータクエリAPIは、複数のメタデータフィールドを含む複雑なクエリ (数値、日付、文字列の比較を必要とするクエリなど) に適しているのに対し、検索APIは、ファイルコンテンツ検索を必要とするよりシンプルなクエリや検索に適しています。

詳細については、メタデータクエリAPIと検索APIの概要を参照してください。

Boxのメタデータの詳細については、以下を参照してください。

--

--