簡體   English   中英

將MySQL查詢轉換為mongoDB

[英]Convert MySQL query to mongoDB

我已經開始學習MongoDB並遇到了問題。 我有一個集合名稱為server_logs。

它包含以下列(SOURCE_SERVER,SOURCE_PORT,DESTINATION_PORT,DESTINATION_SERVER,MBYTES)。

我需要將SOURCE_SERVER與MBYTES的總金額轉移到每個SOURCE_SERVER。(但這里還有一點是,如果存在任何source_server,target_server中也存在,那么它們的MBYTES也會在每個SOURCE_SERVER中添加)。

例如:我有下表結構

  SOURCE   S_PORT   DEST    D_PORT  MBYTES
1)server1   446    server2   555     10MB
2)server3   226    server1   666     2MB
3)server1   446    server3   226     5MB

我需要以下結果:

Server1  17MB
Server3  7MB

我已經在mysql中創建了一個查詢,根據傳輸到該SOURCE的數據的MBYTES計算到最高SOURCE。 它工作正常,我通過此查詢獲得MYSQL所需的結果。

SELECT SOURCE, DEST, sum( logs.MBYTES )+(
    SELECT SUM(log.MBYTES) as sum
    from logs as log
    where logs.DEST=log.SOURCE
) AS MBYTES

我想在MongoDB中使用此查詢。 請幫忙..

提前致謝..

雖然這種“自聯接”類型的查詢對於如何使用MongoDB看起來似乎並不明顯,但它可以通過聚合框架完成,但只需要稍微改變一下你的想法。

使用這種形式的MongoDB中的數據,它仍然非常像原始的SQL源:

{ 
    "source" : "server1",
    "s_port" : 446,
    "dest" : "server2", 
    "d_port" : 555, 
    "transferMB" : 10
},
{ 
    "source" : "server3",
    "s_port" : 226,
    "dest" : "server1",
    "d_port" : 666,
    "transferMB" : 2
},
{ 
    "source" : "server1",
    "s_port" : 446, 
    "dest" : "server3",
    "d_port" : 226,
    "transferMB" : 5
}

使用2.6版本的MongoDB,您的查詢將如下所示:

db.logs.aggregate([

    // Project a "type" tag in order to transform, then unwind
    { "$project": {
         "source": 1,
         "dest": 1,
         "transferMB": 1,
         "type": { "$cond": [ 1,[ "source", "dest" ],0] }
    }},
    { "$unwind": "$type" },

    // Map the "source" and "dest" servers onto the type, keep the source       
    { "$project": {
        "type": 1,
        "tag": { "$cond": [
            { "$eq": [ "$type", "source" ] },
            "$source",
            "$dest"
        ]},
        "mbytes": "$transferMB",
        "source": 1
    }},

    // Group for totals, keep an array of the "source" for each
    { "$group": {
        "_id": "$tag",
        "mbytes": { "$sum": "$mbytes" },
        "source": { "$addToSet": "$source" }
    }},


    // Unwind that array
    { "$unwind": "$source" },

    // Is our grouped tag one on the sources? Inner join simulate
    { "$project": {
        "mbytes": 1,
        "matched": { "$eq": [ "$source", "$_id" ] }
    }},

    // Filter the results that did not match
    { "$match": { "matched": true }},


    // Discard duplicates for each server tag
    { "$group": { 
        "_id": "$_id",
        "mbytes": { "$first": "$mbytes" }
    }}
])

對於2.6及更高版本,您可以使用一些額外的運算符來簡化此操作,或者至少使用不同的運算符:

db.logs.aggregate([

    // Project a "type" tag in order to transform, then unwind
    { "$project": {
         "source": 1,
         "dest": 1,
         "transferMB": 1,
         "type": { "$literal": [ "source", "dest" ] }
    }},
    { "$unwind": "$type" },

    // Map the "source" and "dest" servers onto the type, keep the source       
    { "$project": {
        "type": 1,
        "tag": { "$cond": [
            { "$eq": [ "$type", "source" ] },
            "$source",
            "$dest"
        ]},
        "mbytes": "$transferMB",
        "source": 1
    }},

    // Group for totals, keep an array of the "source" for each
    { "$group": {
        "_id": "$tag",
        "mbytes": { "$sum": "$mbytes" },
        "source": { "$addToSet": "$source" }
    }},

    // Co-erce the server tag into an array ( of one element )
    { "$group": {
        "_id": "$_id",
        "mbytes": { "$first": "$mbytes" },
        "source": { "$first": "$source" },
        "tags": { "$push": "$_id" }
    }},

    // User set intersection to find common element count of arrays
    { "$project": {
       "mbytes": 1,
       "matched": { "$size": { 
           "$setIntersection": [
               "$source",
               "$tags"
           ]
       }}
    }},

    // Filter those that had nothing in common
    { "$match": { "matched": { "$gt": 0 } }},

    // Remove the un-required field
    { "$project": { "mbytes": 1 }}
])

兩種形式都會產生結果:

{ "_id" : "server1", "mbytes" : 17 }
{ "_id" : "server3", "mbytes" : 7 }

兩者的一般原則是,通過保留有效“源”服務器的列表,您可以“過濾”組合結果,以便只列出作為源的那些將記錄其總傳輸。

因此,您可以使用幾種技術來“重新塑造”,“組合”和“過濾”您的文檔以獲得所需的結果。

閱讀有關聚合運算符的更多信息,同時值得一看的是文檔中的SQL to Aggregation映射圖表 ,以便您了解轉換常見操作。

甚至可以在Stack Overflow上瀏覽標簽,以找到一些有趣的轉換操作。

您可以使用聚合框架:

db.logs.aggregate([
    {$group:{_id:"$SOURCE",MBYTES:{$sum:"$MBYTES"}}}
])

假設您在MBYTES字段中只有MBYTES值。 因此,您將擁有:

{
    _id: server1,
    MBYTES: 17
},
{
    _id: server3,
    MBYTES: 7
}

萬一你必須計算這個也為服務器出現在DEST字段你應該使用map-reduce方法:

var mapF = function(){
    emit(this.SOURCE,this.MBYTES);
    emit(this.DEST,this.MBYTES);
}

var reduceF = function(serverId,mbytesValues){
    var reduced = {
        server: serverId,
        mbytes: 0
    };

    mbytesValues.forEach(function(value) {
        reduced.mbytes += value;
    });

    return reduced;
}

db.logs.mapReduce(mapF,reduceF,{out:"server_stats"});

之后您可以在server_stats集合中找到結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM