У меня есть MongoDB с коллекцией: люди.
[
{
_id: 0,
name: "lucas",
properties: [
{
Name: "powers",
Values: [
"fireball",
"icebeam",
"thunderbolt"
]
},
{
Name: "weakness",
Values: [
"poison",
"rain"
]
}
]
},
{
_id: 1,
name: "cage",
properties: [
{
Name: "powers",
Values: [
"flight",
"strength",
"fireball"
]
},
{
Name: "weakness",
Values: [
"lightning",
"ice"
]
}
]
},
{
_id: 2,
name: "joe",
properties: [
{
Name: "powers",
Values: [
"immortality",
"strength",
"flight"
]
}
]
},
{
_id: 3,
name: "bob",
properties: [
{
Name: "weakness",
Values: [
"cold",
"flu",
"no food"
]
}
]
}
]
Я намеренно исключил свойство «слабость» для «Джо» и «силы» для «Боб», поскольку не у всех людей есть слабости или способности. Я не уверен, как сортировать все записи на основе свойств «степени» по их значениям. Предполагая, что у меня 50 героев, я хочу вернуть все записи, но отсортированные по свойствам, и вернуть их с разбивкой на страницы.
Привет @YongShun, извини, это определенно должно было быть в моем вопросе, но да, первая сортировка по мощности свойств по длине/значению элемента по возрастанию/убыванию
В запросе MongoDB вам необходимо извлечь массив степеней и его размер (powersLength
) перед выполнением сортировки.
После этого удалите оба поля, чтобы они не отображались в результате.
db.collection.aggregate([
{
$set: {
properties: {
$map: {
input: "$properties",
in: {
$mergeObjects: [
"$$this",
{
Values: {
$sortArray: {
input: "$$this.Values",
sortBy: 1
}
}
}
]
}
}
}
}
},
{
$set: {
powers: {
$getField: {
field: "Values",
input: {
$first: {
$filter: {
input: "$properties",
cond: {
$eq: [
"$$this.Name",
"powers"
]
}
}
}
}
}
}
}
},
{
$set: {
powersLength: {
$size: {
$ifNull: [
"$powers",
[]
]
}
}
}
},
{
$sort: {
powersLength: -1,
powers: 1
}
},
{
$unset: [
"powers",
"powersLength"
]
}
])
Я думаю, что в синтаксисе драйвера MongoDB .NET это сложно и, возможно, недостижимо с полным синтаксисом Fluent API.
Но вы можете перевести запрос на BsonDocument
через MongoDB Compass (функция экспорта в язык).
var pipeline = new BsonDocument[]
{
new BsonDocument("$set",
new BsonDocument("powers",
new BsonDocument("$getField",
new BsonDocument
{
{ "field", "Values" },
{ "input",
new BsonDocument("$first",
new BsonDocument("$filter",
new BsonDocument
{
{ "input", "$properties" },
{ "cond",
new BsonDocument("$eq",
new BsonArray
{
"$$this.Name",
"powers"
}) }
})) }
}))),
new BsonDocument("$set",
new BsonDocument("powersLength",
new BsonDocument("$size",
new BsonDocument("$ifNull",
new BsonArray
{
"$powers",
new BsonArray()
})))),
new BsonDocument("$sort",
new BsonDocument
{
{ "powersLength", -1 },
{ "powers", 1 }
}),
new BsonDocument("$unset",
new BsonArray
{
"powers",
"powersLength"
})
};
var result = await _col.Aggregate<People>(pipeline)
.ToListAsync();
Или поработайте с Fluent API частично:
var setStageFirst = new BsonDocument("$set",
new BsonDocument("powers",
new BsonDocument("$getField",
new BsonDocument
{
{ "field", "Values" },
{ "input",
new BsonDocument("$first",
new BsonDocument("$filter",
new BsonDocument
{
{ "input", "$properties" },
{ "cond",
new BsonDocument("$eq",
new BsonArray
{
"$$this.Name",
"powers"
})
}
}))
}
})));
var setStageSecond = new BsonDocument("$set",
new BsonDocument("powers",
new BsonDocument("$getField",
new BsonDocument
{
{ "field", "Values" },
{ "input",
new BsonDocument("$first",
new BsonDocument("$filter",
new BsonDocument
{
{ "input", "$properties" },
{ "cond",
new BsonDocument("$eq",
new BsonArray
{
"$$this.Name",
"powers"
})
}
}))
}
})));
var setStageThird = new BsonDocument("$set",
new BsonDocument("powersLength",
new BsonDocument("$size",
new BsonDocument("$ifNull",
new BsonArray
{
"$powers",
new BsonArray()
}))));
var sortStage = new BsonDocument
{
{ "powersLength", -1 },
{ "powers", 1 }
};
var unsetStage = new BsonDocument("$unset",
new BsonArray
{
"powers",
"powersLength"
});
var result = await _col.Aggregate()
.AppendStage<BsonDocument>(setStageFirst)
.AppendStage<BsonDocument>(setStageSecond)
.AppendStage<BsonDocument>(setStageThird)
.Sort(sortStage)
.AppendStage<People>(unsetStage)
.ToListAsync();
Спасибо, поиграв с ним на детской площадке, я думаю, что понимаю это немного лучше. Мне нужно больше практики в запросах mongodb. Если бы я хотел отсортировать степени перед сортировкой по длине, мог бы я просто поставить sortField перед условием?
На этапе $sort
вы можете настроить последовательность оформления заказа. Итак, вам нужно поместить powers: 1
перед powersLength: -1
, чтобы документ упорядочился сначала по массиву powers
, а затем по powersLength
по убыванию. Документы
о, я понимаю, как поменять последовательность на восходящий/нисходящий. Но если бы я хотел также отсортировать значения, добавил бы я сортировку перед условием в первом наборе?
Хорошо, насколько я понимаю, вы хотите отсортировать последовательность в массиве Values
?
Да, я смотрю, возможно ли это, и если да, то где будет размещена дополнительная сортировка.
Должно быть как в этой демо
Круто, я вижу, что он создает еще один объект набора, который сам обрабатывает сортировку значений.
Думаю, было бы здорово, если бы вы описали или предоставили желаемый результат. 1. Сортировать по степеням свойств по длине/значению элемента по возрастанию/убыванию? 2. Сначала отсортировать элемент, содержащий степени?