IBM Cloud Docs
建立選取元表示式

建立選取元表示式

一般而言,只要您有一個採用引數的運算子,該引數本身就可以是另一個具有其本身引數的運算子。 此擴充會啟用更複雜的選取元表示式。

當您使用 JSON 類型的索引時,組合或陣列邏輯運算子 (例如 $regex) 可能會導致完整資料庫掃描,導致效能不佳。 僅限相等運算子,例如 $eq$gt$gte$lt$lte (但不是 $ne),啟用索引查閱。 若要確保有效使用索引,請分析 每一個查詢的 解譯計劃

大部分選取元表示式的運作方式與您預期的運算子完全相同。 $regex 運算子所使用的比對演算法目前 基於 Perl Compatible Regular Expression(PCRE)程式庫。 不過,並非所有 PCRE 程式庫都已實作。 此外, $regex 運算子的部分部分已超出 PCRE 提供的範圍。 如需實作內容的相關資訊,請參閱 Erlang 正規表示式 資訊。

排序語法

sort 欄位包含欄位名稱及方向配對的清單,以基本陣列表示。 第一個欄位名稱及方向配對是排序的最上層。 進一步的配對 (如果提供的話) 會指定下一個排序層次。

排序欄位可以是任何欄位。 必要的話,請對子欄位使用帶點表示法。

方向值為 asc (升冪),desc (降冪)。

如果您排除方向值,則會使用預設 asc

請參閱下列簡式排序語法範例:

[
	{
		"fieldName1": "desc"
	},
	{
		"fieldName2": "desc"
	}
]

請參閱下列簡式排序範例,並假設兩個欄位的預設方向都是 "ascending":

[
	"fieldNameA", "fieldNameB"
]

一般需求是使用選取器來搜尋部分內容,然後根據指定的欄位,以偏好的方向來排序結果。

若要使用排序,必須定義包含排序欄位的索引。 如果使用 json 索引,則必須以與排序相同的順序指定欄位。

目前,IBM Cloudant 查詢不支援多個具有不同排序順序的欄位,因此方向必須全部遞增或全部遞減。

如果方向是遞增,您可以使用字串而非物件來指定排序欄位。

對於排序查詢中針對 text 索引的欄位名稱,如果無法判定要排序的欄位類型,則可能需要指定欄位類型。 例如:

{
	"<fieldname>:string": "asc"
}
何時指定欄位類型
查詢使用哪個索引? 欄位類型需求
JSON 索引
所有文件中所有欄位的文字索引 如果資料庫包含排序欄位具有一種類型的文件,請在查詢中指定排序欄位。 此外,如果查詢包含排序欄位具有不同類型的文件,請在查詢中指定排序欄位。
任何其他文字索引 指定查詢中所有排序欄位的類型。

當您使用語法時,會建立所有文件中所有欄位的文字索引: "index": {}.

當欄位包含不同的資料類型時,未定義排序順序。 此性質是文字與視圖索引之間的重要差異。 在未來版本中,具有不同資料類型之欄位的排序行為可能會變更。

請參閱下列使用排序的簡式查詢範例:

{
	"selector": {
		"Actor_name": "Robert De Niro"
	},
	"sort": [
		{
			"Actor_name": "asc"
		},
		{
			"Movie_runtime": "asc"
		}
	]
}

過濾欄位

當您從資料庫中選取時,可以確切指定針對文件傳回的欄位。 這兩個優點顯示在下列清單中:

  • 您的結果僅限於應用程式所需的文件部分。
  • 減少回應的大小。

要傳回的欄位指定為陣列。

回應中只包含指定的過濾器欄位。_id 或其他 meta 資料欄位不會自動併入。

請參閱下列從相符文件選擇性擷取欄位的範例:

{
	"selector": {
		"Actor_name": "Robert De Niro"
	},
	"fields": [
		"Actor_name",
		"Movie_year",
		"_id",
		"_rev"
	]
}

分頁

IBM Cloudant 查詢支援透過書籤欄位進行分頁。 每個 _find 回應都包含書籤- IBM Cloudant 用來決定在稍後進行查詢時要從何處回復的記號。 若要取得下一組查詢結果,請將前一個回應中收到的書籤新增至下一個要求。 請記得保持選取元相同,否則您會收到非預期的結果。 若要向後分頁,您可以使用前一個書籤來傳回前一個結果集。

書籤的存在並不保證會有更多結果。 您可以比較傳回的結果數目與所要求的頁面大小,來測試您是否在結果集的結尾。 如果傳回的結果小於限制,則結果集中未傳回更多結果。

說明計劃

IBM Cloudant 除非您在查詢時指定索引,否則查詢會選擇用於回應查詢的索引。

當您指定要使用的索引時, IBM Cloudant 查詢使用下列邏輯:

  • 查詢規劃程式會查看選取器區段,並尋找與查詢中使用的運算子及欄位最相符的索引。 如果兩個以上 JSON 類型索引相符,則偏好索引中具有最少欄位數的索引。 如果仍有兩個以上候選項索引存在,則會選擇具有第一個字母名稱的索引。
  • 如果 json 類型索引 text 類型索引可能都滿足選取器,依預設會選擇 json 索引。
  • 當符合下列條件時,會選擇 text 類型索引:
    • json 類型索引 text 類型索引存在於相同的欄位中 (例如 fieldone)。
    • 只能使用 text 類型索引來滿足選取元。

例如,假設您具有 text 類型索引和 json 欄位 foo 的類型索引,並且您想要使用類似於下列範例的選取器:

{
	"foo": {
		"$in": ["red","blue","green"]
	}
}

IBM Cloudant 查詢會使用 text 類型索引,因為 json 類型索引無法滿足選取器。

不過,您可以使用具有相同索引的不同選取器:

{
	"foo": {
		"$gt": 2
	}
}

在此範例中, IBM Cloudant 查詢會使用 json 類型索引,因為這兩種類型的索引都可以滿足選取器。

若要識別特定查詢正在使用的索引,請將 POST 傳送至資料庫的 _explain 端點,並以查詢作為資料。 使用中索引的詳細資料會顯示在結果內的 index 物件中。

請參閱下列使用 HTTP 的範例,以顯示如何識別用來回答查詢的索引:

POST /movies/_explain HTTP/1.1
Host: $SERVICE_URL
Content-Type: application/json
{
	"selector": {
		"$text": "Pacino",
		"year": 2010
	}
}

請參閱下列使用指令行的範例,以顯示如何識別用來回答查詢的索引:

curl "$SERVICE_URL/movies/_explain" \
	-X POST \
	-H "Content-Type: application/json" \
	-d '{
		"selector": {
			"$text": "Pacino",
			"year": 2010
		}
	}'
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.ExplainResult;
import com.ibm.cloud.cloudant.v1.model.PostExplainOptions;

import java.util.HashMap;
import java.util.Map;

Cloudant service = Cloudant.newInstance();

Map<String, Object> selector = new HashMap<>();
selector.put("$text", "Pacino");
selector.put("year", 2010);

PostExplainOptions explainOptions =
    new PostExplainOptions.Builder()
        .db("movies")
        .selector(selector)
        .build();

ExplainResult response =
    service.postExplain(explainOptions).execute()
        .getResult();

System.out.println(response);
import { CloudantV1 } from '@ibm-cloud/cloudant';

const service = CloudantV1.newInstance({});

let selector: CloudantV1.Selector = {
    '$text': 'Pacino',
    'year': 2010
};

service.postExplain({
  db: 'movies',
  selector: selector
}).then(response => {
  console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1

service = CloudantV1.new_instance()

response = service.post_find(
  db='movies',
  selector={'$text': 'Pacino', 'year': 2010}
).get_result()

print(response)
postExplainOptions := service.NewPostExplainOptions(
    "movies",
    map[string]interface{}{
        "$text": "Pacino",
        "year":  2010,
    },
)

explainResult, _, err := service.PostExplain(postExplainOptions)
if err != nil {
  panic(err)
}

b, _ := json.MarshalIndent(explainResult, "", "  ")
fmt.Println(string(b))

前一個 Go 範例需要下列匯入區塊:

import (
   "encoding/json"
   "fmt"
   "github.com/IBM/cloudant-go-sdk/cloudantv1"
)

請參閱下列範例回應,其中顯示用來回答查詢的索引:

{
	"dbname": "$ACCOUNT/movies",
	"index": {
		"ddoc": "_design/32372935e14bed00cc6db4fc9efca0f1537d34a8",
		"name": "32372935e14bed00cc6db4fc9efca0f1537d34a8",
		"type": "text",
		"def": {
			"default_analyzer": "keyword",
			"default_field": {},
			"selector": {},
			"fields": []
		}
	},
	"selector": {
		"$and": [
			{
				"$default": {
					"$text": "Pacino"
				}
			},
			{
				"year": {
					"$eq": 2010
				}
			}
		]
	},
	"opts": {
		"use_index": [],
		"bookmark": [],
		"limit": 10000000000,
		"skip": 0,
		"sort": {},
		"fields": "all_fields",
		"r": [
			49
		],
		"conflicts": false
	},
	"limit": 200,
	"skip": 0,
	"fields": "all_fields",
	"query": "(($default:Pacino) AND (year_3anumber:2010))",
	"sort": "relevance"
}

若要指示查詢使用特定索引,請將 use_index 參數新增至查詢。

use_index 參數的值採用下列其中一種格式:

  • "use_index": "$DDOC"
  • "use_index": ["$DDOC","$INDEX_NAME"]

請參閱下列範例查詢,並提供使用特定索引的指示:

{
	"selector": {
		"$text": "Pacino",
		"year": 2010
	},
	"use_index": "_design/32372935e14bed00cc6db4fc9efca0f1537d34a8"
}