2016-05-26 213 views
3

我有一個遵循這種結構的幾個文件:

{ 
    "queue-type": <integer>, 
    "participants": [{ 
    "id": <integer>, 
    "level": <level>, 
    "flags": <integer> 
    }] 
} 

而且有一個多鍵指數participants.id

在代碼中,有一個查找查詢,如下:db.queues.find({"participants.id": {"$in": [2, 3, 4]}}),其產生以下結果:

{"queue-type": 1, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]} 
{"queue-type": 25, "participants": [{"id": 5, "level": 10, "flags":4},{"id": 15, "level": 10, "flags":8},{"id": 4, "level": 10, "flags":8}]} 

有什麼辦法也取回這是用來匹配的元素查詢?

{"queue-type": 1, "_matched": 2, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]} 
{"queue-type": 25, "_matched": 4, "participants": [{"id": 5, "level": 10, "flags":4},{"id": 15, "level": 10, "flags":8},{"id": 4, "level": 10, "flags":8}]} 

PS:喜歡的東西,我試圖避免通過[2, 3, 4]participants陣列循環,因爲它們更強壯。

例子: 隊列

{"queue-type": 1, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]} 
{"queue-type": 2, "participants": [{"id": 3, "level": 10, "flags":0}]} 
{"queue-type": 3, "participants": [{"id": 4, "level": 10, "flags":4},{"id": 5, "level": 10, "flags":8}]} 
{"queue-type": 4, "participants": [{"id": 7, "level": 10, "flags":4},{"id": 8, "level": 10, "flags":8},{"id": 9, "level": 10, "flags":8}]} 

結果我希望檢索:

db.queues.find({"participants.id": {"$in": [2]}}); 
{"queue-type": 1, "_matched": 2, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]} 

注意 「_matched」 元素是一樣的 'participant.id' 搜索查詢給定

另一個例子:

db.queues.find({"participants.id": {"$in": [2, 3, 6]}}); 
{"queue-type": 1, "_matched": 2, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]} 
{"queue-type": 2, "_matched": 3, "participants": [{"id": 3, "level": 10, "flags":0}]} 

多場比賽例如:

db.queues.find({"participants.id": {"$in": [1, 2, 3]}}); 
{"queue-type": 1, "_matched": 1, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]} 
{"queue-type": 1, "_matched": 2, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]} 
{"queue-type": 2, "_matched": 3, "participants": [{"id": 3, "level": 10, "flags":0}]} 

一個沒有很好的解決辦法是簡單地複製了 '參與者' 的數據( '參與者-CPY'),然後運行:

db.queues.find({"participants-cpy.id": {"$in": [2]}}, {"participants-cpy.$":1, "participants":1, "_id": 1, "queue-type":1}) 

可能用於檢索用於「匹配」查詢的元素,但會生成重複的數據 - 這是非常糟糕的:p

+0

你說的'這是用來匹配上query'元素是什麼意思? – Shrabanee

+0

對不起,在這裏不清楚。 在查詢中,我總是傳遞一個列表(在示例[2,3,4]中),但大多數時間只是列表中的一個元素將成功匹配。要更新帖子以試圖說清楚。 –

+0

我明白你想要什麼。你可以嘗試使用'aggregate'和'$ group',這是獲得你想要的東西的方法。 – Shrabanee

回答

1

常規find查詢在這裏不起作用。您需要使用聚合框架。在您的管道中,只需使用$match管道運算符僅選擇符合查詢條件的那些文檔。

流水線中的下一個也是最後一個階段是您使用的$project階段,在您的文檔中添加新字段「_matched」。如果你仔細想想,你會意識到新字段只是包含出現在你的「partcipantsId」數組/列表中的元素以及文檔中「參與者」字段的所有「id」中的數組。

要獲得該值,只需使用$map$setIntersection運算符在participantId數組和「參與者」的「id」數組上執行一組交集操作。請注意,結果數組僅包含唯一條目,因爲$setIntersection會過濾掉重複項。

participantsId = [1, 2, 3] 
db.queues.aggregate([ 
    { "$match": { "participants.id": { "$in": participantsId } } }, 
    { "$project": { 
     "_matched": { 
      "$setIntersection": [ 
       { "$map": { 
        "input": "$participants", 
        "as": "p", 
        "in": "$$p.id" 
       }}, 
       participantsId 
      ] 
     }, 
     "queue-type": 1, 
     "participants": 1 
    }} 
]) 
相關問題