[英]How can I optimize this query in mongo db?
這是查詢:
const tags = await mongo
.collection("positive")
.aggregate<{ word: string; count: number }>([
{
$lookup: {
from: "search_history",
localField: "search_id",
foreignField: "search_id",
as: "history",
pipeline: [
{
$match: {
created_at: { $gt: prevSunday.toISOString() },
},
},
{
$group: {
_id: "$url",
},
},
],
},
},
{
$match: {
history: { $ne: [] },
},
},
{
$group: {
_id: "$word",
url: {
$addToSet: "$history._id",
},
},
},
{
$project: {
_id: 0,
word: "$_id",
count: {
$size: {
$reduce: {
input: "$url",
initialValue: [],
in: {
$concatArrays: ["$$value", "$$this"],
},
},
},
},
},
},
{
$sort: {
count: -1,
},
},
{
$limit: 50,
},
])
.toArray();
我想我需要一個索引,但不確定如何或在哪里添加。
在我們確認該方法本身是合理的滿足所需的應用程序邏輯之后,也許應該重新審視該操作的性能。
在性能方面,如果目的是處理每個文檔,則無法提高positive
收集的效率。 根據定義,處理所有文檔需要完整的集合掃描。
為了有效地支持search_history
集合上的$lookup
,您可能希望確認{ search_id: 1, created_at: 1, url: 1 }
上的索引存在。 提供.explain("allPlansExecution")
output 將使我們能夠更好地了解當前的性能特征。
更新問題以包含有關架構和聚合目的的詳細信息對於理解整體情況非常有幫助。 僅查看聚合,它似乎正在執行以下操作:
positive
集合中的每個文檔,添加一個名為history
的新字段。search_history
集合的url
值的列表,其中相應的文檔具有匹配的search_id
值並且是在上created_at
之后創建的。history
字段具有至少一個條目的文檔。word
將結果組合在一起。 這里使用了$addToSet
運算符,但它可能會生成一個 arrays 數組,而不是去重復的url
數組。url
的數量,並按按該大小降序排序的word
返回前50
結果。這是你想要的嗎? 特別是以下方面可能值得確認:
positive
集合中的每個文檔? 可能是這種情況,但如果沒有任何模式/用例上下文,就無法判斷。url
的尺寸計算是否正確? 在為$group
執行$addToSet
而不是為后續的$project
使用$reduce
時,您似乎可能需要使用$map
。最好的辦法是限制傳遞到每個階段的文檔數量。 只有在匹配時,mongo 才會在聚合中使用索引,最大使用 1 個索引。
所以最好的辦法是在一個非常嚴格的索引字段上進行匹配。
此外,請注意$limit
、 $skip
和$sample
不是萬能的,因為它們仍然會掃描整個集合。
一種有效限制第一階段選擇的文檔數量的方法是使用“分頁”。 你可以讓它像這樣工作:
每 X 請求一次
每一個請求
used
的密鑰和nbChunks
獲取當前要掃描的塊id:${used%nbChunks}
和id:${(used%nbChunks)+1}
$match
進行聚合_id:{$gte: ObjectId(id0), $lt: ObjectId(id1)}) }
used
增量,如果used > X
則更新塊進一步優化
如果使用 redis,請在每個鍵后面加上${cluster.worker.id}:
以避免熱鍵。
筆記
$lt
$match
是第一階段,_id 是一個被索引的字段,這個第一階段非常快,並且限制了掃描的最大 Y 個文檔。希望它有所幫助=)如果需要,請務必詢問更多=)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.