Mongo 排名结果

Mongo ranking results

我有一个collection喜欢

db.books.insertMany([
  {"products" : [{"name": "name1", "ids": [4, 5, 6]}], "author" : "Dante", "shelf": "a" },
  { "products" : [{"name": "name1", "ids": [4, 5]}], "author" : "Homer", "shelf": "a" },
  { "products" : [{"name": "name1", "ids": [2]}], "author" : "Dante", "shelf": "b" },
])

我想检索所有“书架”为 'a' 的文档 并按 2 个条件排序: 1 - 按作者 2 - products.ids 不包含 6 的文档应该是第一个。

有人能帮忙吗?

您可以试试这个查询:

  • 首先 $match shelf 带有“a”的值。
  • 然后创建一个辅助值,如果 6 不存在,则为 true products.ids,否则为 false。
  • 然后 $sort 按您想要的值。
  • 并使用$project去掉辅助值
db.collection.aggregate([
  {
    "$match": {"shelf": "a"}
  },
  {
    "$set": {
      "rank": {
        "$eq": [
          {
            "$filter": {
              "input": "$products",
              "cond": {"$in": [6,"$$this.ids"]}
            }
          },[]
        ]
      }
    }
  },
  {
    "$sort": {
      "rank": -1,
      "author": 1
    }
  },
  {
    "$project": {"rank": 0}
  }
])

示例here

这是一个根据作者+“不包含 6”进行更精细排序的变体。

db.foo.aggregate([
    {$match: {shelf:'a'}}
    ,{$unwind: '$products'}
    ,{$addFields: {sortMarker: {$cond: [
    {$in: [6, '$products.ids']},
        "Z",  // THEN make sortMarker at the end                                 
        "A"   // ELSE make sortMarker at the start                               
    ]}
                  }}

    ,{$sort: {'author':1, 'sortMarker':1}}
]);

给定此输入集:

{"products" : [
        {"name": "name3", "ids": [6, 7]},
        {"name": "name2", "ids": [4, 5]}
    ],
     "author" : "Homer",
     "shelf": "a" },

    {"products" : [
    {"name": "name1", "ids": [4, 5, 6]},
    {"name": "name4", "ids": [9]},
    {"name": "name7", "ids": [9,6]},
        {"name": "name7", "ids": [10]}

    ],
     "author" : "Dante",
     "shelf": "a"},

    { "products" : [
    {"name": "name1", "ids": [2]}
    ], "author" : "Dante",
      "shelf": "b"}

产生这个结果:

{
    "_id" : 1,
    "products" : {
        "name" : "name4",
        "ids" : [
            9
        ]
    },
    "author" : "Dante",
    "shelf" : "a",
    "sortMarker" : "A"
}
{
    "_id" : 1,
    "products" : {
        "name" : "name7",
        "ids" : [
            10
        ]
    },
    "author" : "Dante",
    "shelf" : "a",
    "sortMarker" : "A"
}
{
    "_id" : 1,
    "products" : {
        "name" : "name1",
        "ids" : [
            4,
            5,
            6
        ]
    },
    "author" : "Dante",
    "shelf" : "a",
    "sortMarker" : "Z"
}
{
    "_id" : 1,
    "products" : {
        "name" : "name7",
        "ids" : [
            9,
            6
        ]
    },
    "author" : "Dante",
    "shelf" : "a",
    "sortMarker" : "Z"
}
{
    "_id" : 0,
    "products" : {
        "name" : "name2",
        "ids" : [
            4,
            5
        ]
    },
    "author" : "Homer",
    "shelf" : "a",
    "sortMarker" : "A"
}
{
    "_id" : 0,
    "products" : {
        "name" : "name3",
        "ids" : [
            6,
            7
        ]
    },
    "author" : "Homer",
    "shelf" : "a",
    "sortMarker" : "Z"
}

可选地,可以在 $sort:

之后添加此阶段
    {$group: {_id: '$author', products: {$push: '$products'}}}

并且这会将排序后的“不包含6然后包含6”项目再次组合在一起作为author打包的数组; $push 保留顺序。请注意,我们只需要 author in _id 因为匹配的是 one 货架。如果匹配的货架不止一个,那么我们需要:

    {$group: {_id: {author:'$author',shelf:'$shelf'}, products: {$push: '$products'}}}