共用方式為


在 Azure DocumentDB 中建立萬用字元索引

對於結構中欄位集合不穩定的工作負載,可以使用萬用字索引來支援對任意或未知欄位的查詢,以達到最佳效能。

萬用字元索引在以下情境下可能很有幫助:

  • 查詢過濾文件中任一欄位,使得用單一指令索引所有欄位比單獨索引每個欄位更簡單。
  • 篩選文件中大部分欄位的查詢會使編製所有欄位的索引而非透過單一命令編製幾個欄位的索引更容易。

索引所有欄位

設置通配符索引以便於查詢所有可能的文件欄位,包括那些未知或動態名稱的欄位。

db.collection.createIndex( { "$**": 1 } )

這很重要

對於大型收藏,我們建議採用本文後面所述的替代方法。

包含或排除特定欄位

萬用字元索引也可以限制為特定欄位,同時排除使特定欄位成為編製索引的目標。 讓我們來回顧以下 JSON 的範例。

{
    "firstName": "Steve",
    "lastName": "Smith",
    "companyName": "Microsoft",
    "division": "Azure",
    "timeInOrgInYears": 7
}

我們可以控制索引行為,這個範例限制在firstNamelastNametimeInOrgInYears欄位上建立索引。

db.collection.createIndex( { "$**": 1 },
                           {"wildcardProjection" : {  "firstName": 0
                                                    , "lastName": 0
                                                    , "companyName": 1
                                                    , "division": 1
                                                    , "timeInOrgInYears": 0
                                                   }
                           }
                         )

在 wildcardProjection 文件中,值 0 或 1 表示欄位是否被納入索引(1)或從索引中排除(0)。

索引所有欄位的替代方案

此範例說明了一個簡單的變通方法,用於在 Azure DocumentDB 的通配索引功能正式普遍可用前,減少建立個別索引的工作量。

請參考下方的 json 文件:

{
    "firstName": "Steve",
    "lastName": "Smith",
    "companyName": "Microsoft",
    "division": "Azure",
    "subDivision": "Data & AI",
    "timeInOrgInYears": 7,
    "roles": [
        {
            "teamName" : "Windows",
            "teamSubName" "Operating Systems",
            "timeInTeamInYears": 3
        },
        {
            "teamName" : "Devices",
            "teamSubName" "Surface",
            "timeInTeamInYears": 2
        },
        {
            "teamName" : "Devices",
            "teamSubName" "Surface",
            "timeInTeamInYears": 2
        }
    ]
}

當使用萬用字碼索引時,封面下會建立以下索引。

  • db.collection.createIndex({"firstName", 1})
  • db.collection.createIndex({“lastName”, 1})
  • db.collection.createIndex({“companyName”, 1})
  • db.collection.createIndex({“division”, 1})
  • db.collection.createIndex({“subDivision”, 1})
  • db.collection.createIndex({“timeInOrgInYears”, 1})
  • db.collection.createIndex({“subDivision”, 1})
  • db.collection.createIndex({"roles.teamName", 1})
  • db.collection.createIndex({“roles.teamSubName”, 1})
  • db.collection.createIndex({"roles.timeInTeamInYears", 1})

雖然這份範例文件只需明確索引 10 個欄位的組合,但擁有數百甚至數千個欄位的大型文件,單獨索引欄位時會變得繁瑣且容易出錯。

本文件其餘部分所詳述的 jar 檔案,讓大型文件中的欄位索引變得更簡單。 jar 會將範例 JSON 文件作為輸入,解析文件,並為每個欄位執行 createIndex 指令,無需使用者介入。

先決條件

爪哇21

虛擬機部署完成後,使用 SSH 連接機器,並使用以下指令安裝 CQLSH:

# Install default-jdk
sudo apt update
sudo apt install openjdk-21-jdk

用示例jar為所有欄位建立獨立索引

克隆包含 Java 範例的儲存庫,遍歷 JSON 文件結構中的每個欄位,並對文件中每個欄位執行 createIndex 操作。

git clone https://github.com/Azure-Samples/cosmosdb-mongodb-vcore-wildcard-indexing.git

如果解決方案沒有需要更改,則不需要建立複製的儲存庫。 已建置的可跑動 jar 名為 azure-cosmosdb-mongo-data-indexer-1.0-SNAPSHOT.jar,已經包含在 runnableJar/ 資料夾中。 您可以指定下列必要參數來執行 jar:

  • Azure DocumentDB 叢集連線字串,以及叢集配置時使用的使用者名稱和密碼
  • Azure DocumentDB 資料庫
  • 要編製索引的集合
  • json 檔案的位置,其中包含集合的文件結構。 此文件由 jar 檔案解析,以擷取每個欄位並執行個別的 createIndex 操作。
java -jar azure-cosmosdb-mongo-data-indexer-1.0-SNAPSHOT.jar mongodb+srv://<user>:<password>@abinav-test-benchmarking.global.mongocluster.cosmos.azure.com/?tls=true&authMechanism=SCRAM-SHA-256&retrywrites=false&maxIdleTimeMS=120000 cosmicworks employee sampleEmployee.json

追蹤 createIndex 操作的狀態

jar 檔案的設計是為了不等待每個 createIndex 操作的回應。 索引會在伺服器上非同步建立,並可追蹤叢集上索引建置操作的進度。

請考慮此範例來追蹤 'cosmicworks' 資料庫上的索引編製進度。

use cosmicworks;
db.currentOp()

當 createIndex 操作進行中時,回應如下:

{
  "inprog": [
    {
      "shard": "defaultShard",
      "active": true,
      "type": "op",
      "opid": "30000451493:1719209762286363",
      "op_prefix": 30000451493,
      "currentOpTime": "2024-06-24T06:16:02.000Z",
      "secs_running": 0,
      "command": { "aggregate": "" },
      "op": "command",
      "waitingForLock": false
    },
    {
      "shard": "defaultShard",
      "active": true,
      "type": "op",
      "opid": "30000451876:1719209638351743",
      "op_prefix": 30000451876,
      "currentOpTime": "2024-06-24T06:13:58.000Z",
      "secs_running": 124,
      "command": { "createIndexes": "" },
      "op": "workerCommand",
      "waitingForLock": false,
      "progress": {},
      "msg": ""
    }
  ],
  "ok": 1
}

後續步驟