【问题标题】:How to sort data in Mongo in a custom order如何以自定义顺序对 Mongo 中的数据进行排序
【发布时间】:2017-04-09 18:56:26
【问题描述】:

如何使用 Mongo 功能对这些数据进行排序:

输入

{ "_id" : 1, "domainName" : "test1.com", "hosting" : "hostgator.com" }
{ "_id" : 2, "domainName" : "test2.com", "hosting" : "aws.amazon.com"}
{ "_id" : 3, "domainName" : "test3.com", "hosting" : "aws.amazon.com" }
{ "_id" : 4, "domainName" : "test4.com", "hosting" : "hostgator.com" }
{ "_id" : 5, "domainName" : "test5.com", "hosting" : "aws.amazon.com" }
{ "_id" : 6, "domainName" : "test6.com", "hosting" : "cloud.google.com" }
{ "_id" : 7, "domainName" : "test7.com", "hosting" : "aws.amazon.com" }
{ "_id" : 8, "domainName" : "test8.com", "hosting" : "hostgator.com" }
{ "_id" : 9, "domainName" : "test9.com", "hosting" : "cloud.google.com" }
{ "_id" : 10, "domainName" : "test10.com", "hosting" : "godaddy.com" }

按托管字段的顺序,得到结果,例如按这个顺序:

1) 首先 - 所有的上帝;

2) 第二个 - 所有 AWS;

3) 以及接下来的一切。

输出

{
    "result" : [
            {

                    "_id" : 10, 
                    "domainName" : "test10.com",
                    "hosting" : "godaddy.com"
            },
            {
                    "_id" : 2, 
                    "domainName" : "test2.com",
                    "hosting" : "aws.amazon.com"
            },
            {
                    "_id" : 3, 
                    "domainName" : "test3.com",
                    "hosting" : "aws.amazon.com"
            },
            {
                    "_id" : 5, 
                    "domainName" : "test5.com",
                    "hosting" : "aws.amazon.com"
            },
            {
                    "_id" : 7, 
                    "domainName" : "test7.com",
                    "hosting" : "aws.amazon.com"
            },
            {
                    "_id" : 1, 
                    "domainName" : "test1.com",
                    "hosting" : "hostgator.com"
            },
            {
                    "_id" : 4, 
                    "domainName" : "test4.com",
                    "hosting" : "hostgator.com"
            },
            {
                    "_id" : 6, 
                    "domainName" : "test6.com",
                    "hosting" : "cloud.google.com"
            },
            {
                    "_id" : 8, 
                    "domainName" : "test8.com",
                    "hosting" : "hostgator.com"
            },
            {
                    "_id" : 9, 
                    "domainName" : "test9.com",
                    "hosting" : "cloud.google.com"
            },
    ]
    }

通过这个示例,我想以更相关的方式为用户返回结果。在原始任务中,我想使用其他几个集合对其进行排序,这些集合提供更多信息。

但是如果你能帮助我完成之前的任务就足够了吗?

UPD:关于问题的第二部分。

另一个任务是如何从一个集合中返回可排序的数据,依赖于另一个集合。

例子:

第一个集合与之前给出的相同:

 { "_id" : 1, "domainName" : "test1.com", "hosting" : "hostgator.com" }
 ...

第二个集合,提供一些关于托管的附加信息:

{ '_id': 123, 'quality':'best', 'hostings': ["hostgator.com",  "aws.amazon.com"]},
{ '_id': 321, 'quality':'good', 'hostings': ["cloud.google.com"]},
{ '_id': 345, 'quality':'bad', 'hostings': ["godaddy.com"]},

结果,我需要按以下顺序从第一个收集数据返回:

1) 首先所有好的主机 2)其次一切都好 3) 第三个都不好

输出:

{
"result" : [
        //Best:
        {
                "_id" : 1, 
                "domainName" : "test1.com",
                "hosting" : "hostgator.com"
        },
        {
                "_id" : 4, 
                "domainName" : "test4.com",
                "hosting" : "hostgator.com"
        },
        {
                "_id" : 8, 
                "domainName" : "test8.com",
                "hosting" : "hostgator.com"
        },
        {
                "_id" : 2, 
                "domainName" : "test2.com",
                "hosting" : "aws.amazon.com"
        },
        {
                "_id" : 3, 
                "domainName" : "test3.com",
                "hosting" : "aws.amazon.com"
        },
        {
                "_id" : 5, 
                "domainName" : "test5.com",
                "hosting" : "aws.amazon.com"
        },
        {
                "_id" : 7, 
                "domainName" : "test7.com",
                "hosting" : "aws.amazon.com"
        },

       // Good:
        {
                "_id" : 9, 
                "domainName" : "test9.com",
                "hosting" : "cloud.google.com"
        },
        {
                "_id" : 6, 
                "domainName" : "test6.com",
                "hosting" : "cloud.google.com"
        },

       //Bad
        {
                "_id" : 10, 
                "domainName" : "test10.com",
                "hosting" : "godaddy.com"
        }
]
}

更新 2

我在前面的例子中得到了很好的答案和例子。太感谢了!但我举了另一个例子。

我需要比较 3 个集合的 ID 以按顺序排序 - 第一个:朋友,第二个:“请求”,以及:其他用户。

输入

db.friends.find({userId: currentUser});
    // {"_id" : "PgC7LrtaZtQsShtzT", "userId" : "tHuxnWxFLHvcpRgHb", "friendId" : "jZagPF7bd4aW8agXb",}
db.requests.find({userId: currentUser});
   // looks like friend but with 'requesterId'

现在我需要聚合“用户”集合,定义与前两个集合(朋友、请求)匹配的分数。

使用提供的答案,我管理了结果,但只有一个集合。我怎样才能用 3 或多个来制作这个?

【问题讨论】:

  • 是否假定godaddy 总是表示字符串godaddy.com 并且与aws 和aws.amazon.com 相同?
  • 是的,它是字符串。
  • 在问题的第一部分你是对的,但它是第二部分,我找不到任何关于这个的想法。

标签: mongodb mongodb-query


【解决方案1】:

您可以将每个hosting 投影到由整数表示的单独类型中,最后对这些整数进行排序。在下面的聚合管道中进行了说明

[
{$lookup: {
    from: 'secondCollectionStoringQuality',
    localField: 'hosting',
    foreignField: 'hostings',
    as: 'nw'
    }},
{$unwind: '$nw'},
{$project: {
        domainName: 1,
        hosting: 1,
        type: {
            $cond: [
                {$eq: ['$nw.quality', 'best']},
                0,
                {$cond: [
                    {$eq: ['$nw.quality', 'good']},
                    1,
                    2
                    ]}
            ]
        }
    }},
    {$sort: {type: 1}}
]

【讨论】:

  • 感谢您的回答。这对我的问题很有帮助!可能您知道如何使排序依赖于另一个集合吗?例如:我需要通过在另一个集合中指定的参数对有问题的相同数据进行排序。像这样:{_id: 321, 'quality': 'good', 'hosting': ['godaddy.com', 'aws.amazon.com']};{_id: 123, 'quality': 'bad', 'hosting': ['hostgator.com', ... , ... ,]}我需要从第一个集合开始排队,第一个托管是好还是坏?
  • 你能用这些细节更新问题吗?
  • 抱歉再次打扰您。但是如果我遇到问题,我不能使用给定的例子。这个例子很适合比较两个集合,但是如何对 3 个或更多集合做同样的事情呢?我更新了问题 - 更新 2。
  • 如何让$eq不区分大小写?
  • 值得注意的是,如果这是一个大型或高度查询的集合:您将无法在聚合管道中为此利用索引。如果您有这个问题,请考虑在持久化文档时使用计算字段。
【解决方案2】:

这个解决方案怎么样?

1) N 个条件。

2) 需要的排序顺序可以通过参数传递。

[{
        "$lookup": {
            "from": "secondCollectionStoringQuality",
            "localField": "hosting",
            "foreignField": "hostings",
            "as": "nw"
        }
    },
    {
        "$unwind": "$nw"
    },
    {
        "$project": {
            "domainName": 1,
            "hosting": 1,
            "type": {
                "$indexOfArray": [
                    ["best", "good"], "$nw.quality"
                ]
            }
        }
    },
    {
      "$project": {
          "domainName": 1,
          "hosting": 1,
          "type": {
              "$cond": [ {"$eq":["$type", -1]},  10000, "$type"]
          }
      }
    },
    {
        "$sort": {
            "type": 1
        }
    }
]

【讨论】:

    【解决方案3】:

    如果数据存在于数组中,则上述答案有效。你可以在没有$lookup$project 的情况下实现这一点。

    .aggregate([
       {$addFields: {
          sortId: {
             $cond: [{$eq: ['$hosting', 'godaddy.com']},0,
                {$cond: [{$eq: ['$hosting', 'aws.amazon.com']},1,2]
          }
       }},
      {$sort: {sortId: 1}}
    ])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-28
      • 1970-01-01
      • 2014-04-19
      • 1970-01-01
      相关资源
      最近更新 更多