【问题标题】:Mongodb complex aggregate query sortingMongoDB复杂聚合查询排序
【发布时间】:2021-03-09 14:41:49
【问题描述】:

问题是:打印所有住宿的列表,首先按价格排序,然后按提供的便利设施数量。 但是,有两个问题,第一个是 price 是一个以 $ 开头的字符串,必须先将其转换为整数才能正确排序,另一个问题,我不知道如何计算属性的数量每个文件的便利设施。

My JSON is like this:
[
  {
    "_id": "5bf31f8c856a12c73c888cee",
    "index": 0,
    "guid": "f99844b5-7ecd-4c90-860f-b79a742fcac1",
    "isActive": true,
    "registered": "2012-06-14T02:14:30 -02:00",
    "host": {
      "name": "Grimes",
      "surname": "Terrell",
      "gender": "male",
      "age": 55,
      "picture": "https://api.adorable.io/avatars/285/GrimesTerrell.png",
      "languages": [
        "spanish",
        "slovenian",
        "english"
      ],
      "contact": {
        "company": "QUANTALIA",
        "email": "grimesterrell@quantalia.com",
        "phone": "+1 (987) 474-3543"
      },
      "reviews": [
        {
          "reviewer": "Mae Ryan",
          "date": "2015-06-01T02:41:46 -02:00",
          "helpful": 8,
          "kind": 1,
          "responsive": 5
        },
        {
          "reviewer": "Nixon Johnson",
          "date": "2016-02-08T10:35:12 -01:00",
          "helpful": 1,
          "kind": 1,
          "responsive": 9
        },
        {
          "reviewer": "Dorothy Copeland",
          "date": "2016-07-17T12:44:31 -02:00",
          "helpful": 3,
          "kind": 3,
          "responsive": 4
        },
        {
          "reviewer": "Kathleen Roth",
          "date": "2014-12-26T04:38:36 -01:00",
          "helpful": 10,
          "kind": 3,
          "responsive": 5
        },
        {
          "reviewer": "Hallie Hart",
          "date": "2016-02-14T10:21:50 -01:00",
          "helpful": 9,
          "kind": 4,
          "responsive": 9
        }
      ]
    },
    "lodging": {
      "price": "$86",
      "address": {
        "street": "645 Louisa Street",
        "city": "Fairhaven",
        "state": "Nebraska",
        "coordinates": [
          5.439653,
          30.761532
        ]
      },
      "amenities": {
        "parking": true,
        "petsAllowed": true,
        "airConditioning": true,
        "elevator": true
      },
      "reviews": [
        {
          "reviewer": "Susanne Walton",
          "date": "2018-03-20T04:50:18 -01:00",
          "cleanliness": 8,
          "location": 1,
          "food": 10
        },
        {
          "reviewer": "Henrietta Manning",
          "date": "2017-12-14T07:05:46 -01:00",
          "cleanliness": 10,
          "location": 5,
          "food": 1
        },
        {
          "reviewer": "Newman West",
          "date": "2018-05-07T05:23:55 -02:00",
          "cleanliness": 9,
          "location": 10,
          "food": 6
        },
        {
          "reviewer": "Brennan Rowland",
          "date": "2016-09-20T04:49:15 -02:00",
          "cleanliness": 10,
          "location": 1,
          "food": 8
        },
        {
          "reviewer": "Beulah Lambert",
          "date": "2016-04-20T11:51:43 -02:00",
          "cleanliness": 4,
          "location": 8,
          "food": 9
        },
        {
          "reviewer": "Joseph Mcdowell",
          "date": "2015-02-10T12:14:20 -01:00",
          "cleanliness": 7,
          "location": 9,
          "food": 3
        }
      ]
    }
  },
  {
    "_id": "5bf31f8c20b3acacc2194faa",
    "index": 1,
    "guid": "7d65ed39-13d0-4121-bacd-3b6e1c1daa17",
    "isActive": true,
    "registered": "2016-04-22T08:54:50 -02:00",
    "host": {
      "name": "Schultz",
      "surname": "French",
      "gender": "male",
      "age": 24,
      "picture": "https://api.adorable.io/avatars/285/SchultzFrench.png",
      "languages": [
        "spanish",
        "polish"
      ],
      "contact": {
        "company": "ORBEAN",
        "email": "schultzfrench@orbean.com",
        "phone": "+1 (972) 497-2462"
      },
      "reviews": [
        {
          "reviewer": "Prince Berg",
          "date": "2017-11-10T01:18:41 -01:00",
          "helpful": 5,
          "kind": 5,
          "responsive": 6
        }
      ]
    },
    "lodging": {
      "price": "$45",
      "address": {
        "street": "323 Polar Street",
        "city": "Lutsen",
        "state": "Louisiana",
        "coordinates": [
          30.447311,
          24.791852
        ]
      },
      "amenities": {
        "freeWifi": true,
        "parking": true,
        "petsAllowed": true,
        "elevator": true,
        "balcony": true
      },
      "reviews": [
        {
          "reviewer": "Mariana Ayers",
          "date": "2014-04-13T08:30:02 -02:00",
          "cleanliness": 9,
          "location": 6,
          "food": 4
        },
        {
          "reviewer": "Cole Simmons",
          "date": "2015-05-07T06:00:09 -02:00",
          "cleanliness": 1,
          "location": 3,
          "food": 2
        }
      ]
    }
  },
  {
    "_id": "5bf31f8c8af00ea536cb92d7",
    "index": 2,
    "guid": "74ef5317-4949-4259-836c-43cc05eed32c",
    "isActive": true,
    "registered": "2010-09-12T02:38:43 -02:00",
    "host": {
      "name": "Nicholson",
      "surname": "Cooper",
      "gender": "male",
      "age": 71,
      "picture": "https://api.adorable.io/avatars/285/NicholsonCooper.png",
      "languages": [
        "german",
        "english"
      ],
      "contact": {
        "company": "COMTENT",
        "email": "nicholsoncooper@comtent.com",
        "phone": "+1 (934) 472-2934"
      },
      "reviews": [
        {
          "reviewer": "Corinne Barber",
          "date": "2017-01-22T08:16:59 -01:00",
          "helpful": 9,
          "kind": 6,
          "responsive": 3
        },
        {
          "reviewer": "Callahan Mann",
          "date": "2015-08-18T03:46:07 -02:00",
          "helpful": 9,
          "kind": 5,
          "responsive": 9
        },
        {
          "reviewer": "Alberta Chan",
          "date": "2016-07-27T01:59:55 -02:00",
          "helpful": 9,
          "kind": 2,
          "responsive": 1
        },
        {
          "reviewer": "Hampton Horn",
          "date": "2017-08-08T04:20:22 -02:00",
          "helpful": 9,
          "kind": 4,
          "responsive": 2
        },
        {
          "reviewer": "Castillo Farley",
          "date": "2015-07-04T12:00:38 -02:00",
          "helpful": 9,
          "kind": 3,
          "responsive": 6
        },
        {
          "reviewer": "Imogene Henson",
          "date": "2014-12-22T04:15:35 -01:00",
          "helpful": 4,
          "kind": 6,
          "responsive": 10
        }
      ]
    },
    "lodging": {
      "price": "$91",
      "address": {
        "street": "979 Varet Street",
        "city": "Allendale",
        "state": "Illinois",
        "coordinates": [
          24.238092,
          -51.522132
        ]
      },
      "amenities": {
        "freeWifi": true,
        "parking": true,
        "petsAllowed": true,
        "airConditioning": true,
        "balcony": true
      },
      "reviews": []
    }
  },
  {
.
.
.

我尝试过这样的事情,但是,我对 mongodb 很陌生。

db.lodging.aggregate(
[
{$project: {"substring": {$substr: ["lodging.price", 1,-1 ]}} }, // String to substring (number).
{$project: {intfield: {$toInt: substring}}}, // Integer from substring for order by.
{$project: {}} // TODO: Number of amenities.
{$sort: {intfield: -1, numamenities: -1}}
]
);

【问题讨论】:

  • 到底为什么要将price 值存储为字符串?使用数值数据类型。同样适用于 date - 使用 Date 对象而不是字符串。
  • @Wernfried Domscheit 这是一个课堂作业,我昨天向教授问了同样的问题,他告诉我这是为了使用一些 mongodb 函数。
  • 什么是“一些 mongodb 函数”?

标签: javascript mongodb sorting aggregate


【解决方案1】:

这样的聚合可以解决问题:

db.lodging.aggregate([
  {
    $addFields: {
      "intfield": {
        $toInt: {
          $substr: ["$lodging.price", 1, -1]
        }
      },
      "numamenities": {
        $size: {
          $objectToArray: "$lodging.amenities"
        }
      }
    }
  },
  {
    $sort: {
      intfield: -1,
      numamenities: -1
    }
  }
])

我使用的第一个聚合阶段是$addFields。我没有使用$project 的原因是因为只有$project 文档中的字段才能进入下一阶段。因此,当您编写此{$project: {"substring": {$substr: ["lodging.price", 1,-1 ]}} } 时,下一阶段唯一可用的字段将是substring。为了传递文档的其余部分,最好使用 $addFields。

在计算intfield 时,您可能会注意到我传递的值是$lodging.price,带有$ 而不是lodging.price$ 让 MongoDB 知道您需要 value of the field lodging.price 而不是值为 lodging.price 的字符串。

对于numamenities,我使用$objectToArraylodging.amenities字段转为数组,这样就可以使用$size操作符来获取字段个数。

现在intfieldnumamenities 已添加到每个文档中,剩下要做的就是$sort

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-12
    • 1970-01-01
    • 2019-11-04
    • 1970-01-01
    • 2014-10-21
    • 2016-03-11
    • 2015-11-19
    • 1970-01-01
    相关资源
    最近更新 更多