全部產品
Search
文件中心

OpenSearch:layer子句

更新時間:Jul 13, 2024

子句說明

分層查詢一種查詢文法的擴充,主要功能是增強查詢文法對於召回過程的控制能力,讓應用可以根據自己的使用情境來加速文檔召回過程,提高系統整體效能,擴充的功能主要有以下幾點:

  • 允許使用者通過某些方式選擇召回的區間

  • 對於不同區間可以選擇召回的先後順序

  • 對於不同區間可以指定不同的query來影響召回集

子句文法

名詞介紹

name

description

seek

查詢過程中,查詢到一個doc的操作

docid

HA3內部對文檔的編號,查詢時會按docid從小到大查詢。

[查詢]區間/range

查詢時一個docid的範圍,這裡的range是指會被查詢的docid的範圍。

[查詢]層/layer

層是由一個或者多個range組成的,層主要作用是決定查詢區間的優先順序(把不同range放到不同層)。[查詢]層/layer[查詢]區間/rangedocidseekname

查詢文法

{
  "layer" : [
  ]
}

選擇召回區間

對於召回區間的控制主要通過layer文法來實現:

一個layer子句可以由多個single_layer組成,一個single_layer主要有兩個元素:

  • quota:用於設定當前層建議召回的doc個數,這裡有幾個點需要注意:

    • quota與rank_size的關係:各層quota總和不會大於rank_size,例如rank_size=10,quota:5;quota:7,這樣最終第二層的quota會被截斷到5。

    • 當前層quota有剩餘的情況下,會自動把quota累加到下一層。

    • 由於層內的每個區間之間的doc不一定滿足前面的doc比後面doc要好,所以quota有兩種作用機制,一種是每尋找到一個doc,就檢查一次quota是否有剩餘,另一種是在當前層內無視quota限制(依舊被rank_size限制),尋找完當前層,最後看是否有剩餘,若有剩餘則累加到下一層

    • 當使用者顯示指定layer子句的時候,每層quota預設值是0,quota的最大值為uint32_t的最大值。

  • range :用於確定當前層的doc範圍,如果不寫,範圍區間為所有doc,及[0,docCount)。range文法基本工作原理是通過使用者給定的attribute,逐級計算最終需要seek的doc範圍。需要注意的點:

    • 文法中用到的必須是attribute,不能是需要計算的運算式

    • 文法中用到的attribute必須與離線排序方式相符,否則會自動轉換為查詢全部區間。

    • 文法中用到的attribute必須要是連續出現的,不可以中間插入擴充關鍵字(%sorted,%docid等)

    • 除了attribute外我們還支援幾種擴充語句:%sorted(這一層查詢排過序的全量和增量),%unsorted(這一層查詢未排序的資料,即時資料等),%other(除去前面層以外的範圍),%docid(直接指定docid區間查詢),%segmentid(直接指定segmentid區間查詢),%percent(指定這個範圍百分比範圍的區間查詢)

    • 如果使用者在分層子句中沒有指定%sorted,%unsorted關鍵字,引擎會自動為使用者添加,預設模式是每層都是sorted,最後如果結果數不夠會為使用者多查一層即時資料

選擇不同區間的不同query

對於不同查詢層,可以使用不同的查詢詞,或者選擇不同的倒排鏈。不同query通過分號隔開,當layer的數目大於query數目時,會自動用最後一條query填充剩餘層。

使用樣本:

本節將介紹分層查詢與一些引擎提供的其他功能結合使用的情境下,如何搭配使用分層查詢。

構建索引時文檔排序,查詢指定召回區間

在使用離線的排序功能時,文檔是全域有序的,例如,按照網站排序後,同一個網站的文檔在索引中是連續的一段,當在某個網站內部查詢時,可以利用這個資訊來加快seek的速度,假定網站對應的attribute是site_id,查詢的網站ID為1和7,查詢詞為iphone:

{
  "layer" : [
    {
      "range" : { 
        "fields" : [
          {
            "field" : "site_id",
            "values" : [1,7]
          }
        ]
      },
      "quota" : 5000
    }
  ]
}

或者如果網站1和7中查詢結果不夠的情況下,使用者還想查詢網站5和10的結果作為補充,可以這樣:

{
  "layer" : [
    {
      "range" : { 
        "fields" : [
          {
            "field" : "site_id",
            "values" : [1,7]
          }
        ]
      },
      "quota" : 5000
    },
    {
      "range" : { 
        "fields" : [
          {
            "field" : "site_id",
            "values" : [5,10]
          }
        ]
      },
      "quota" : 0
    }
  ]
}

由於是希望第一層結果不夠的情況下才查詢第二層,所以第二層的quota設定為0(或者不寫)。當然,使用者還可以進行多樣性召回:

{
  "layer" : [
    {
      "range" : { 
        "fields" : [
          {
            "field" : "site_id",
            "values" : [1,7]
          }
        ]
      },
      "quota" : 4000
    },
    {
      "range" : { 
        "fields" : [
          {
            "field" : "site_id",
            "values" : [5,10]
          }
        ]
      },
      "quota" : 1000
    }
  ]
}

對於離線排序是多維的情況,也可以支援多維區間的定位,還是以站內查詢為例,離線排序是先按網站排序,網站相同的,按照網頁的靜態分排序,這種時候,查詢希望召回靜態分大於100的網頁,查詢文法如下:

{
  "layer" : [
    {
      "range" : { 
        "fields" : [
          {
            "field" : "site_id",
            "values" : [1,7]
          },
          {
            "field" : "static_score",
            "values" : "[100,]"
          }
        ]
      },
      "quota" : 4000
    }
  ]
}

註:區間範圍表示加雙引號

多query查詢

在某些情況下,使用者的查詢即擔心召回數目是否足夠,又希望召回數不能太多,導致影響查詢效能,比較常見的一類情境是,有多個查詢詞,以A,B為例:

query方式

召回數

效能

A AND B

最少

最好

A OR B

最多

最差

A RANK B/B RANK A

適中

中等

上述的幾種query方式,對於A和B的召回數和效能都不一樣,大部分查詢希望的是有較好的召回,而且召回數不需要太多,這種情況下,固定用某種查詢方式,很難保證結果數和效能都適中。使用多query的方式就可以通過一次查詢來解決這個問題:

{
  "query": "A OR B;A RANK B;A AND B",
  "layer" : [
    {
      "quota" : 1000
    },
    {
      "quota" : 1000
    },
    {
      "quota" : 1000
    }
  ]
}

這種查詢方式可以兼顧召迴文檔數目和效能,對於查詢詞的關聯程度也有比較大的提升(對於大召回可以命中一些A AND B的結果,對於小召回可以通過A OR B來儘可能多召回)。

需要考慮時效性的查詢

有時候使用者會希望查詢結果的時效性比較好,在這種情況下使用者會希望先查詢即時的無序索引,之後再查詢全量和增量的有序索引,使用者也可以在有序索引中指定先查詢後面的一部分資料,再查前面的一部分資料,可以用percent實現

例如使用者想要先查詢時效性最好的即時索引,結果不夠的話查詢有序索引中後50%的doc,最後查詢前50%的doc,查詢詞為iphone:

{
  "layer" : [
    {
      "range" : { 
        "index_type" : "%unsorted"
      },
      "quota" : 5000
    },
    {
      "range" : { 
        "index_type" : "%sorted",
        "fields" : [
          {
            "field" : "service_id",
            "values" : [1,3]
          }
        ],
        "percent" : "[50,100)"
      },
      "quota" : 0
    },
    {
      "range" : { 
        "index_type" : "%sorted",
        "fields" : [
          {
            "field" : "service_id",
            "values" : [1,3]
          }
        ],
        "percent" : "[0,50)"
      },
      "quota" : 0
    }
  ]
}

註:percent關鍵字中可以指定不同多個區間,區間是左閉右開的

注意事項

  • layer子句是可選子句