我有對象的集合至少X值,每個具有場稱爲指紋,其包含20個散列:查找條目,其中陣列A包含從陣列乙
{
title: 'The Chronicles of Narnia',
authors: ['C.S. Lewis'],
fingerprint: ['50e...', 'ae2...', ...]
}
我然後有另外20的查詢指紋哈希值。我想要做的是找到至少共享X哈希的所有條目。換句話說,兩個陣列的交集必須是一定的大小。
我有一個使用MySQL的類似系統的舊實現。有查詢看起來是這樣的:
SELECT *
FROM Document d
INNER JOIN Fingerprint f
ON d.id = f.document_id
WHERE f.whorl IN (:hashes)
GROUP BY d.id
HAVING COUNT(d.id) >= X
在Fingerprint
表中的每個條目包含文檔ID和指紋單螺紋。每個文檔將有Fingerprint
20條目。
據我瞭解,這個查詢正在做什麼是每當一個螺紋匹配時複製文檔,然後按獨特的文檔分組。這看起來有些浪費,但它有效。
我想在MongoDB中重新實現這個系統,但我沒有太多的運氣。我能得到的所有條目的列表共享至少一個或所有的旋渦:
at least one: db.objects.find({ fingerprint: {$in: [hashes]})
all: db.objects.find({ fingerprint: {$all: [hashes]})
而且我明白,我可以在應用層掃描此列表中找到我之後的比賽。如果我預計數以百萬計的對象(目前大約150萬),那麼這似乎是一個壞主意。
我已經看過了aggregate()
功能,但對我已經無法改進:
db.objects.aggregate({$match: {fingerprint: {$in: [hashes]}}})
在這裏,我想我能集團和過濾:
db.objects.aggregate({$match: {fingerprint: {$in: [hashes]}}},
{$group: {_id: "$_id", matches: {$sum: 1}}})
在這裏,我是試圖複製MySQL查詢所做的事情:爲每個匹配發出一個文檔,然後對這些文檔進行計數。當然,這裏我們只發一次文件,不管有多少比賽。
然後我想到$unwind
匹配的列表,但每次產生20個文件。
理想的情況下,會有一個$some
運營商,我可以用這樣的:
db.objects.find(fingerprint: {$some: {from: [hashes], count: X}})
是這樣的可能,高效的什麼?我希望能夠響應用戶的搜索來運行這些查詢,所以我認爲MapReduce不存在問題?
感謝
你非常接近找到自己的答案 - 關鍵是先放棄$展開,然後匹配,重新組合再次匹配。 –