第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

檢查數(shù)組中的每個(gè)元素是否都符合條件

檢查數(shù)組中的每個(gè)元素是否都符合條件

嚕嚕噠 2019-11-19 10:36:50
我有一些文件:date: Dateusers: [  { user: 1, group: 1 }  { user: 5, group: 2 }]date: Dateusers: [  { user: 1, group: 1 }  { user: 3, group: 2 }]我想查詢?cè)摷弦圆檎宜形臋n,其中我的用戶數(shù)組中的每個(gè)用戶ID都位于另一個(gè)數(shù)組[1、5、7]中。在此示例中,僅第一個(gè)文檔匹配。我一直能找到的最佳解決方案是:$where: function() {   var ids = [1, 5, 7];  return this.users.every(function(u) {     return ids.indexOf(u.user) !== -1;  });}不幸的是,這似乎損害了性能,在$ where文檔中指出:$ where評(píng)估JavaScript,無法利用索引。如何改善此查詢?
查看完整描述

3 回答

?
阿波羅的戰(zhàn)車

TA貢獻(xiàn)1862條經(jīng)驗(yàn) 獲得超6個(gè)贊

您想要的查詢是這樣的:


db.collection.find({"users":{"$not":{"$elemMatch":{"user":{$nin:[1,5,7]}}}}})

這就是說,找到所有沒有元素不在列表1,5,7之外的文檔。


查看完整回答
反對(duì) 回復(fù) 2019-11-19
?
森欄

TA貢獻(xiàn)1810條經(jīng)驗(yàn) 獲得超5個(gè)贊

我不知道更好,但是有幾種不同的方法可以解決此問題,具體取決于您可用的MongoDB版本。


不太確定這是否符合您的意圖,但是所示查詢將與第一個(gè)文檔示例匹配,因?yàn)樵趯?shí)現(xiàn)邏輯時(shí),您正在匹配文檔數(shù)組中必須包含在樣本數(shù)組中的元素。


因此,如果您實(shí)際上希望文檔包含所有這些元素,那么$all操作員將是顯而易見的選擇:


db.collection.find({ "users.user": { "$all": [ 1, 5, 7 ] } })

但是,在假設(shè)您的邏輯實(shí)際上是預(yù)期的前提下,至少根據(jù)建議,您可以通過與$in運(yùn)算符組合來“過濾”這些結(jié)果,從而減少需要您處理的文檔$where**條件在評(píng)估的JavaScript中:


db.collection.find({

    "users.user": { "$in": [ 1, 5, 7 ] },

    "$where": function() { 

        var ids = [1, 5, 7];

        return this.users.every(function(u) { 

            return ids.indexOf(u.user) !== -1;

        });

    }

})

盡管實(shí)際掃描的結(jié)果將與匹配文檔中數(shù)組中元素的數(shù)量相乘,但您會(huì)得到一個(gè)索引,但是與沒有附加過濾器相比,它仍然更好。


甚至可能是你考慮的邏輯抽象$and結(jié)合使用,運(yùn)營商$or也可能是$size根據(jù)您的實(shí)際情況數(shù)組操作:


db.collection.find({

    "$or": [

        { "users.user": { "$all": [ 1, 5, 7 ] } },

        { "users.user": { "$all": [ 1, 5 ] } },

        { "users.user": { "$all": [ 1, 7 ] } },

        { "users": { "$size": 1 }, "users.user": 1 },

        { "users": { "$size": 1 }, "users.user": 5 },

        { "users": { "$size": 1 }, "users.user": 7 }

    ]

})

因此,這是匹配條件所有可能排列的產(chǎn)物,但是性能可能會(huì)根據(jù)可用的安裝版本而有所不同。


注意:實(shí)際上,在這種情況下完全失敗,因?yàn)檫@樣做完全不同,并且實(shí)際上導(dǎo)致邏輯上的失敗。$in


備選方案是使用聚合框架,這取決于收集中的文檔數(shù)量,MongoDB 2.6及更高版本的一種方法可能會(huì)影響哪種效率最高。


db.problem.aggregate([

    // Match documents that "could" meet the conditions

    { "$match": { 

        "users.user": { "$in": [ 1, 5, 7 ] } 

    }},


    // Keep your original document and a copy of the array

    { "$project": {

        "_id": {

            "_id": "$_id",

            "date": "$date",

            "users": "$users"

        },

        "users": 1,

    }},


    // Unwind the array copy

    { "$unwind": "$users" },


    // Just keeping the "user" element value

    { "$group": {

        "_id": "$_id",

        "users": { "$push": "$users.user" }

    }},


    // Compare to see if all elements are a member of the desired match

    { "$project": {

        "match": { "$setEquals": [

            { "$setIntersection": [ "$users", [ 1, 5, 7 ] ] },

            "$users"

        ]}

    }},


    // Filter out any documents that did not match

    { "$match": { "match": true } },


    // Return the original document form

    { "$project": {

        "_id": "$_id._id",

        "date": "$_id.date",

        "users": "$_id.users"

    }}

])

因此,該方法使用一些新引入的集合運(yùn)算符來比較內(nèi)容,但是當(dāng)然您需要重組數(shù)組才能進(jìn)行比較。


如所指出的,有一個(gè)直接的運(yùn)算符可以做到這一點(diǎn),$setIsSubset其中在單個(gè)運(yùn)算符中可以實(shí)現(xiàn)上述組合運(yùn)算符的等效功能:


db.collection.aggregate([

    { "$match": { 

        "users.user": { "$in": [ 1,5,7 ] } 

    }},

    { "$project": {

        "_id": {

            "_id": "$_id",

            "date": "$date",

            "users": "$users"

        },

        "users": 1,

    }},

    { "$unwind": "$users" },

    { "$group": {

        "_id": "$_id",

        "users": { "$push": "$users.user" }

    }},

    { "$project": {

        "match": { "$setIsSubset": [ "$users", [ 1, 5, 7 ] ] }

    }},

    { "$match": { "match": true } },

    { "$project": {

        "_id": "$_id._id",

        "date": "$_id.date",

        "users": "$_id.users"

    }}

])

或者采用另一種方法,同時(shí)仍然利用$sizeMongoDB 2.6 中的運(yùn)算符:


db.collection.aggregate([

    // Match documents that "could" meet the conditions

    { "$match": { 

        "users.user": { "$in": [ 1, 5, 7 ] } 

    }},


    // Keep your original document and a copy of the array

    // and a note of it's current size

    { "$project": {

        "_id": {

            "_id": "$_id",

            "date": "$date",

            "users": "$users"

        },

        "users": 1,

        "size": { "$size": "$users" }

    }},


    // Unwind the array copy

    { "$unwind": "$users" },


    // Filter array contents that do not match

    { "$match": { 

        "users.user": { "$in": [ 1, 5, 7 ] } 

    }},


    // Count the array elements that did match

    { "$group": {

        "_id": "$_id",

        "size": { "$first": "$size" },

        "count": { "$sum": 1 }

    }},


    // Compare the original size to the matched count

    { "$project": { 

        "match": { "$eq": [ "$size", "$count" ] } 

    }},


    // Filter out documents that were not the same

    { "$match": { "match": true } },


    // Return the original document form

    { "$project": {

        "_id": "$_id._id",

        "date": "$_id.date",

        "users": "$_id.users"

    }}

])

當(dāng)然,哪一個(gè)仍然可以完成,盡管在2.6之前的版本中要花更長的時(shí)間:


db.collection.aggregate([

    // Match documents that "could" meet the conditions

    { "$match": { 

        "users.user": { "$in": [ 1, 5, 7 ] } 

    }},


    // Keep your original document and a copy of the array

    { "$project": {

        "_id": {

            "_id": "$_id",

            "date": "$date",

            "users": "$users"

        },

        "users": 1,

    }},


    // Unwind the array copy

    { "$unwind": "$users" },


    // Group it back to get it's original size

    { "$group": { 

        "_id": "$_id",

        "users": { "$push": "$users" },

        "size": { "$sum": 1 }

    }},


    // Unwind the array copy again

    { "$unwind": "$users" },


    // Filter array contents that do not match

    { "$match": { 

        "users.user": { "$in": [ 1, 5, 7 ] } 

    }},


    // Count the array elements that did match

    { "$group": {

        "_id": "$_id",

        "size": { "$first": "$size" },

        "count": { "$sum": 1 }

    }},


    // Compare the original size to the matched count

    { "$project": { 

        "match": { "$eq": [ "$size", "$count" ] } 

    }},


    // Filter out documents that were not the same

    { "$match": { "match": true } },


    // Return the original document form

    { "$project": {

        "_id": "$_id._id",

        "date": "$_id.date",

        "users": "$_id.users"

    }}

])

通常,這會(huì)找出不同的方法,嘗試一下,看看哪種方法最適合您。$in與您現(xiàn)有表單的簡單組合很可能是最好的組合。但是在所有情況下,請(qǐng)確保您具有可以選擇的索引:


db.collection.ensureIndex({ "users.user": 1 })

只要您以某種方式訪問它,這將為您提供最佳性能,如此處的所有示例所示。


判決

我對(duì)此很感興趣,因此最終設(shè)計(jì)了一個(gè)測(cè)試用例,以查看性能最佳的產(chǎn)品。因此,首先生成一些測(cè)試數(shù)據(jù):


var batch = [];

for ( var n = 1; n <= 10000; n++ ) {

    var elements = Math.floor(Math.random(10)*10)+1;


    var obj = { date: new Date(), users: [] };

    for ( var x = 0; x < elements; x++ ) {

        var user = Math.floor(Math.random(10)*10)+1,

            group = Math.floor(Math.random(10)*10)+1;


        obj.users.push({ user: user, group: group });

    }


    batch.push( obj );


    if ( n % 500 == 0 ) {

        db.problem.insert( batch );

        batch = [];

    }


集合中有10000個(gè)文檔,其中長度為1..10的隨機(jī)數(shù)組保持1..0的隨機(jī)值,我得出了430個(gè)文檔的匹配計(jì)數(shù)(從$inmatch的7749減少),結(jié)果如下(平均):


JavaScript with $in子句:420ms

總有$size:395ms

帶有組數(shù)組計(jì)數(shù)的聚合:650ms

包含兩個(gè)集合運(yùn)算符的集合:275ms

聚合時(shí)間$setIsSubset:250ms

請(qǐng)注意,除了最后兩個(gè)樣本外,所有樣本均完成了約100ms 的峰值方差,并且最后兩個(gè)樣本均顯示了220ms的響應(yīng)。最大的變化是在JavaScript查詢中,該查詢的結(jié)果也慢了100毫秒。


但是這里的要點(diǎn)是與硬件相關(guān)的,在我的筆記本電腦上的VM下,硬件并不是特別出色,但是可以提供一個(gè)思路。


因此,總體而言,特別是具有集合運(yùn)算符的MongoDB 2.6.1版本顯然會(huì)在性能上勝出,而$setIsSubset作為單個(gè)運(yùn)算符還會(huì)帶來一點(diǎn)額外收益。


鑒于(如2.4兼容方法所示),此過程中的最大開銷將是$unwind語句(超過100ms avg),因此,這特別有趣,因此,$in選擇的平均時(shí)間約為32ms,其余流水線階段將在不到100ms內(nèi)執(zhí)行一般。這樣就給出了聚合與JavaScript性能的相對(duì)概念。


查看完整回答
反對(duì) 回復(fù) 2019-11-19
?
小唯快跑啊

TA貢獻(xiàn)1863條經(jīng)驗(yàn) 獲得超2個(gè)贊

我只是花了大部分時(shí)間試圖通過對(duì)象比較而不是嚴(yán)格的相等性來實(shí)現(xiàn)上述Asya的解決方案。所以我想在這里分享。


假設(shè)您將問題從userIds擴(kuò)展到了完整用戶。您想查找所有文檔,其中其users數(shù)組中的每個(gè)項(xiàng)目都出現(xiàn)在另一個(gè)用戶數(shù)組中:[{user: 1, group: 3}, {user: 2, group: 5},...]


這是行不通的:db.collection.find({"users":{"$not":{"$elemMatch":{"$nin":[{user: 1, group: 3},{user: 2, group: 5},...]}}}}})因?yàn)? nin僅適用于嚴(yán)格的平等。因此,我們需要找到一種不同的方式來表示對(duì)象數(shù)組的“不在數(shù)組中”。并且使用$where會(huì)大大降低查詢速度。


解:


db.collection.find({

 "users": {

   "$not": {

     "$elemMatch": {

       // if all of the OR-blocks are true, element is not in array

       "$and": [{

         // each OR-block == true if element != that user

         "$or": [

           "user": { "ne": 1 },

           "group": { "ne": 3 }

         ]

       }, {

         "$or": [

           "user": { "ne": 2 },

           "group": { "ne": 5 }

         ]

       }, {

         // more users...

       }]

     }

   }

 }

})

完善邏輯:$ elemMatch匹配數(shù)組中沒有用戶的所有文檔。因此$ not將匹配數(shù)組中所有用戶的所有文檔。


查看完整回答
反對(duì) 回復(fù) 2019-11-19
  • 3 回答
  • 0 關(guān)注
  • 1125 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)