ベクターサーチコレクションで_idを指定してみる
以下のようなコードを書いて_idを指定してインデックスにドキュメントを投入してみましょう。
const ossClient = new Client({
...AwsSigv4Signer({
region: process.env.AWS_REGION,
service: ‘aoss’,
getCredentials: () => {
const credentialsProvider = defaultProvider()
return credentialsProvider()
},
}),
node: `https://${process.env.OPENSEARCHSERVERLESS_URL}.${process.env.AWS_REGION}.aoss.amazonaws.com`,
})
const indexName = ‘test-idx’
const docId = ‘example-doc-001’
const document = {
document: {
title: ‘タイトル‘,
content: ‘テストテスト’
},
}
// ドキュメントを登録 (put)
const putResponse = await ossClient.index({
index: indexName,
id: docId,
body: document
})
console.log(‘Indexed document:’, putResponse)
すると以下のようなエラーを吐きます。Document ID is not supported
と明確にエラーを吐いてくれいていますね。
{
“errorType”: “ResponseError”,
“errorMessage”: “illegal_argument_exception: [illegal_argument_exception] Reason: Document ID is not supported in create/index operation request”,
“name”: “ResponseError”,
“meta”: {
“body”: {
“error”: {
“root_cause”: [
{
“type”: “illegal_argument_exception”,
“reason”: “Document ID is not supported in create/index operation request”
}
],
“type”: “illegal_argument_exception”,
“reason”: “Document ID is not supported in create/index operation request”
},
“status”: 400
},
“statusCode”: 400,
“headers”: {
“date”: “Mon, 14 Apr 2025 12:31:43 GMT”,
“content-type”: “application/json; charset=UTF-8”,
“content-length”: “261”,
“x-envoy-upstream-service-time”: “2822”,
“server”: “aoss-amazon-i”,
“x-request-id”: “4453d9a2-989a-9675-9ec9-e6dc986a7605”
},
“meta”: {
“context”: null,
“request”: {
“params”: {
“method”: “PUT”,
“path”: “/test-idx/_doc/example-doc-001”,
“querystring”: “”,
“body”: “{\“document\“:{\“title\“:\“タイトル\“,\“content\“:\“テストテスト\“}}“,
“headers”: {
“user-agent”: “opensearch-js/3.5.1 (linux 5.10.234-246.921.amzn2.x86_64-x64; Node.js v22.14.0)“,
“content-type”: “application/json”,
“content-length”: “68"
},
“timeout”: 30000
},
“options”: {},
“id”: 1
今度はGETで_idを指定してデータを取得してみましょう。作成したドキュメントの返り値から_idを取得してそれをキーにGETを試みます。
const putResponse = await ossClient.index({
index: indexName,
body: document
})
const getResponse = await ossClient.get({
index: indexName,
id: putResponse.body._id
})
以下のようにIDを直接指定しても404エラーが返ってきてデータが取得できません。
{
“errorType”: “ResponseError”,
“errorMessage”: “Response Error”,
“name”: “ResponseError”,
“meta”: {
“body”: {
“_index”: “test-idx”,
“_id”: “1%3A0%3AVu9ONJYB5NNi1KOe2cRi”,
“found”: false
},
“statusCode”: 404,
“headers”: {
“date”: “Mon, 14 Apr 2025 12:38:26 GMT”,
“content-type”: “application/json; charset=UTF-8”,
“content-length”: “72”,
“x-envoy-upstream-service-time”: “1070”,
“server”: “aoss-amazon-s”,
“x-request-id”: “05d98277-bbd6-98ae-9b66-056a05d4fb08”
},
“meta”: {
“context”: null,
“request”: {
“params”: {
“method”: “GET”,
“path”: “/test-idx/_doc/1%253A0%253AVu9ONJYB5NNi1KOe2cRi”,
“querystring”: “”,
“body”: “”,
“headers”: {
“user-agent”: “opensearch-js/3.5.1 (linux 5.10.234-246.921.amzn2.x86_64-x64; Node.js v22.14.0)”
},
“timeout”: 30000
},
“options”: {},
“id”: 2
},
どのようにしてドキュメントデータの更新や削除を行うのか
インデックスを運用していると当然ながら元データの更新や削除が発生したタイミングでOpenSearch側のインデックスのデータも同期が取れなければなりません。_idがクライアントから指定できれば割と簡単にできるのですが、少し工夫が必要となります。検索が可能となる仮のIDのプロパティを作成して、それに対してsearchを行い、OpenSearchの内部的な_idを取得。それを元にしてデータの削除や更新が可能となります。
例えば以下のようにdocumentの中にidというプロパティを作ってしまいます。もちろん、OpenSearch Serverless側では一意性のチェックはしてくれないため、アプリケーション側で管理が必要となります。
{
"document": {
"id": "abc123",
"title": "タイトル",
"content": "テストテスト"
}
}
そしてこのidをキーにしてデータを取得。OpenSearch Serverlessの内部的な_idを取得。特定のドキュメントのupdateが可能となります。
const response = await ossClient.search({
index: indexName,
body: {
query: {
term: {
‘document.id.keyword’: {
value: ‘abc123’,
},
},
},
},
})
await ossClient.update({
index: indexName,
id: response.body.hits.hits[0]._id,
body: {
doc: {
document:{title: ‘あああああ’}
},
},
})
削除についても同様です。searchクエリでマッチしたデータから内部的な_idを取得。それを元にドキュメントの削除を行います。
const response = await ossClient.search({
index: indexName,
body: {
query: {
term: {
‘document.id.keyword’: {
value: ‘abc123’,
},
},
},
},
})
const deleteResponse = await ossClient.delete({
index: indexName,
id: response.body.hits.hits[0]._id,
})
console.log(deleteResponse)
以下の様に削除が完了しました。
body: {
_index: ‘test-idx’,
_id: ‘1%3A0%3AzwxhNJYBRgKqg5cIjGaP’,
_version: 3,
result: ‘deleted’,
_shards: { total: 0, successful: 0, failed: 0 },
_seq_no: 0,
_primary_term: 0
},
statusCode: 200,
_idを用いてのPUTやGETが出来ないのはとても違和感がありますが、上記のようにすることでOpenSearch Serverless内のドキュメントの削除や更新は可能になります。