使用特定订单在mongoDB中排序

时间:2018-01-24 12:35:12

标签: c mongodb mongodb-.net-driver

我目前正在寻找基于数组按特定顺序对子文档Clients进行排序。

mongoDB结构

{
    "_id" : "1033",
    "Name" : "Test",
    "Clients" : [ 
        {
            "Id" : 1033,
            "Types" : [ 
                {
                    "Class" : "C",
                    "Service" : null
                },
                {
                    "Class" : "B",
                    "Service" : null
                }
            ]
        }, 
        {
            "Id" : 156136,
            "Types" : [ 
                {
                    "Class" : "A",
                    "Service" : null
                }, 
                {
                    "Class" : "B",
                    "Service" : null
                }, 
                {
                    "Class" : "C",
                    "Service" : null
                }, 
                {
                    "Class" : "D",
                    "Service" : null
                }
            ]
        }
    ]
}

我需要根据[B, A, D, C]

等数组的顺序显示上述文档

这样输出如下:

{
    "_id" : "1033",
    "Name" : "Test",
    "Clients" : [ 
        {
            "Id" : 1033,
            "Types" : [ 
                {
                    "Class" : "B",
                    "Service" : null
                },
                {
                    "Class" : "C",
                    "Service" : null
                }
            ]
        }, 
        {
            "Id" : 156136,
            "Types" : [ 
                {
                    "Class" : "B",
                    "Service" : null
                }, 
                {
                    "Class" : "A",
                    "Service" : null
                }, 
                {
                    "Class" : "D",
                    "Service" : null
                }, 
                {
                    "Class" : "C",
                    "Service" : null
                }
            ]
        }
    ]
}

你能帮我解决一下这个问题吗?

我目前正在使用.Net的MongoDB驱动程序

3 个答案:

答案 0 :(得分:0)

MongoDB中无法进行自定义排序。您可以按升序或降序排序。

答案 1 :(得分:0)

可以根据指定的here通过聚合进行自定义排序。

答案 2 :(得分:0)

我已经使用 $addFields 和 $indexOfArray 聚合解决了自定义排序的问题。

假设我的文档有两个字段:BouqetId、Name

[
    { "BouqetId" : 2, "Name" : "Name2"},
    { "BouqetId" : 16, "Name" : "Name16"},
    { "BouqetId" : 25, "Name" : "Name25"},
    { "BouqetId" : 15, "Name" : "Name15"},
    { "BouqetId" : 125, "Name" : "Name125"},
    { "BouqetId" : 258, "Name" : "Name258"},
    { "BouqetId" : 127, "Name" : "Name127"}
            ... 
  ]

并且我想搜索带有 ID [258,15,2,16] 的 Bouqet 并通过此订单获取它们。

1/ 我在 $match 聚合中使用 $in 运算符过滤我的集合以获得所需的文档:查看代码中的第一步。

2/ 我使用 $addFields 聚合添加一个名为 Order 的字段,并使用 $indexOfArray 聚合为其分配搜索数组中 BouqetId 的索引。

3/ 最后我使用新添加的 Order 字段对它们进行排序。

4/ 我得到我定制的结果。我可以删除订单字段,但现在可以了。

这里和 Nodejs 中的例子:

var db = client.db("MyDatabase");
var collection = db.collection("Bouqets");
var pipeline = [
    {
        "$match": {
            "BouqetId": {
                "$in": [
                    258,
                    15,
                    2,
                    16
                ]
            }
        }
    }, 
    {
        "$addFields": {
            "Order": {
                "$indexOfArray": [
                    [
                       258,
                       15,
                       2,
                       16
                       ],
                    "$BouqetId"
                ]
            }
        }
    }, 
    {
        "$sort": {
            "Order": 1.0
        }
    }
];

var cursor = collection.aggregate(pipeline);

这是我的结果:

[
    { "BouqetId" : 258, "Name" : "Name258" , "Order" : 0},
    { "BouqetId" : 15, "Name" : "Name15", "Order" : 1},
    { "BouqetId" : 2, "Name" : "Name2", "Order" : 2},
    { "BouqetId" : 16, "Name" : "Name16", "Order" : 3}
]

这里是 C# 中的相同示例:

       IMongoClient client = new MongoClient("mongodb://host:port/");
       IMongoDatabase database = client.GetDatabase("MyDatabase");
       IMongoCollection<BsonDocument> collection = database.GetCollection<BsonDocument>("Bouqets");

       var options = new AggregateOptions()
       {
           AllowDiskUse = false
       };

       // my array 
       var searchArray = new int[] {258, 15, 2, 16}; 


       PipelineDefinition<BsonDocument, BsonDocument> pipeline = new BsonDocument[]
       {
            new BsonDocument("$match", new BsonDocument()
                .Add("BouqetId", new BsonDocument()
                    .Add("$in", new BsonArray(searchArray)
                    )
                )),
            new BsonDocument("$addFields", new BsonDocument()
                .Add("Order", new BsonDocument()
                    .Add("$indexOfArray", new BsonArray()
                        .Add(new BsonArray(searchArray)
                        )
                        .Add("$BouqetId")
                    )
                )),
            new BsonDocument("$sort", new BsonDocument()
                .Add("Order", 1.0))
       };

       var result = collection.Aggregate(pipeline, options).ToList();