totalEstimatedMatches 行为与 Microsoft (Bing) 认知搜索 API (v5)
totalEstimatedMatches behavior with Microsoft (Bing) Cognitive search API (v5)
最近将一些 Bing 搜索 API v2 代码转换为 v5,它可以工作,但我对 "totalEstimatedMatches" 的行为感到好奇。这是一个例子来说明我的问题:
我们网站上的一位用户搜索了一个特定的词。 API 查询 returns 10 个结果(我们的页面大小设置)并且 totalEstimatedMatches 设置为 21。因此我们指示 3 页结果并让用户翻页。
当他们到达第 3 页时,totalEstimatedMatches returns 为 22 而不是 21。看起来奇怪的是,对于这么小的结果集,它不应该已经知道它是 22,但好吧,我可以接受。所有结果都正确显示。
现在如果用户再次从第 3 页返回到第 2 页,则 totalEstimatedMatches 的值再次为 21。这让我有点惊讶,因为一旦结果集被分页,API 可能应该知道有 22 个而不是 21 个结果。
我自 80 年代以来一直是一名专业软件开发人员,所以我知道这是与 API 设计相关的细节问题之一。显然它没有缓存准确数量的结果,或其他任何内容。我只是不记得 V2 搜索 API 中的那种行为(我意识到这是第 3 方代码)。结果的数量非常可靠。
这是否让除我之外的任何人都觉得有点意外?
事实证明,这就是响应 JSON 字段 totalEstimatedMatches
包含单词 ...Estimated...
并且不只是称为 totalMatches
的原因:
"...search engine index does not support an accurate estimation of total match."
取自:News Search API V5 paging results with offset and count
正如人们所料,返回的结果越少,您在 totalEstimatedMatches
值中看到的错误百分比可能就越大。同样,您的查询越复杂(例如 运行 复合查询 ../search?q=(foo OR bar OR foobar)&...
实际上是将 3 个搜索打包到 1 个中)这个值似乎表现出更多的变化。
就是说,我已经设法(至少初步)通过设置 offset == totalEstimatedMatches
并创建一个简单的等效检查函数来弥补这一点。
这是 python 中的一个简单示例:
while True:
if original_totalEstimatedMatches < new_totalEstimatedMatches:
original_totalEstimatedMatches = new_totalEstimatedMatches.copy()
#set_new_offset_and_call_api() is a func that does what it says.
new_totalEstimatedMatches = set_new_offset_and_call_api()
else:
break
重温 API & 我想出了一种无需使用 "totalEstimatedMatches"
return 值即可高效分页的方法:
class ApiWorker(object):
def __init__(self, q):
self.q = q
self.offset = 0
self.result_hashes = set()
self.finished = False
def calc_next_offset(self, resp_urls):
before_adding = len(self.result_hashes)
self.result_hashes.update((hash(i) for i in resp_urls)) #<==abuse of set operations.
after_adding = len(self.result_hashes)
if after_adding == before_adding: #<==then we either got a bunch of duplicates or we're getting very few results back.
self.complete = True
else:
self.offset += len(new_results)
def page_through_results(self, *args, **kwargs):
while not self.finished:
new_resp_urls = ...<call_logic>...
self.calc_next_offset(new_resp_urls)
...<save logic>...
print(f'All unique results for q={self.q} have been obtained.')
一旦获得完整的重复响应,这^将停止分页。
最近将一些 Bing 搜索 API v2 代码转换为 v5,它可以工作,但我对 "totalEstimatedMatches" 的行为感到好奇。这是一个例子来说明我的问题:
我们网站上的一位用户搜索了一个特定的词。 API 查询 returns 10 个结果(我们的页面大小设置)并且 totalEstimatedMatches 设置为 21。因此我们指示 3 页结果并让用户翻页。
当他们到达第 3 页时,totalEstimatedMatches returns 为 22 而不是 21。看起来奇怪的是,对于这么小的结果集,它不应该已经知道它是 22,但好吧,我可以接受。所有结果都正确显示。
现在如果用户再次从第 3 页返回到第 2 页,则 totalEstimatedMatches 的值再次为 21。这让我有点惊讶,因为一旦结果集被分页,API 可能应该知道有 22 个而不是 21 个结果。
我自 80 年代以来一直是一名专业软件开发人员,所以我知道这是与 API 设计相关的细节问题之一。显然它没有缓存准确数量的结果,或其他任何内容。我只是不记得 V2 搜索 API 中的那种行为(我意识到这是第 3 方代码)。结果的数量非常可靠。
这是否让除我之外的任何人都觉得有点意外?
事实证明,这就是响应 JSON 字段 totalEstimatedMatches
包含单词 ...Estimated...
并且不只是称为 totalMatches
的原因:
"...search engine index does not support an accurate estimation of total match."
取自:News Search API V5 paging results with offset and count
正如人们所料,返回的结果越少,您在 totalEstimatedMatches
值中看到的错误百分比可能就越大。同样,您的查询越复杂(例如 运行 复合查询 ../search?q=(foo OR bar OR foobar)&...
实际上是将 3 个搜索打包到 1 个中)这个值似乎表现出更多的变化。
就是说,我已经设法(至少初步)通过设置 offset == totalEstimatedMatches
并创建一个简单的等效检查函数来弥补这一点。
这是 python 中的一个简单示例:
while True:
if original_totalEstimatedMatches < new_totalEstimatedMatches:
original_totalEstimatedMatches = new_totalEstimatedMatches.copy()
#set_new_offset_and_call_api() is a func that does what it says.
new_totalEstimatedMatches = set_new_offset_and_call_api()
else:
break
重温 API & 我想出了一种无需使用 "totalEstimatedMatches"
return 值即可高效分页的方法:
class ApiWorker(object):
def __init__(self, q):
self.q = q
self.offset = 0
self.result_hashes = set()
self.finished = False
def calc_next_offset(self, resp_urls):
before_adding = len(self.result_hashes)
self.result_hashes.update((hash(i) for i in resp_urls)) #<==abuse of set operations.
after_adding = len(self.result_hashes)
if after_adding == before_adding: #<==then we either got a bunch of duplicates or we're getting very few results back.
self.complete = True
else:
self.offset += len(new_results)
def page_through_results(self, *args, **kwargs):
while not self.finished:
new_resp_urls = ...<call_logic>...
self.calc_next_offset(new_resp_urls)
...<save logic>...
print(f'All unique results for q={self.q} have been obtained.')
一旦获得完整的重复响应,这^将停止分页。