Как отсортировать запрос MongoDB для соотношения двух полей в каждом документе? - PullRequest
3 голосов
/ 24 февраля 2011

Предположим, у меня много документов вроде {'a': x, 'b': y}.Предположим, что x и y являются целыми числами.Как я могу сделать что-то вроде find().sort({'a'/'b'})?

Ответы [ 4 ]

1 голос
/ 24 мая 2019

С тех пор, как этот вопрос был задан в 2011 году, MongoDB выпустила структуру агрегирования. Это позволяет вам сортировать по комбинациям полей, и вам не нужно хранить (денормализовать) какие-либо дополнительные поля. Вот как это делается:

db.collection.aggregate([
{
    $match: {
        // Optional criteria to select only some documents to process, such as...
        deleted: null
    }
},
{
    $project: {
        // Need to prefix fields with '$'
        ratio: { $divide: [ "$a", "$b" ] },
    }
},
{
    $sort: { ratio: -1 },
}
]);

Вот и все. Мы используем оператор $ div структуры агрегации .

1 голос
/ 24 февраля 2011

Вы можете добавить третье поле, результат a / b и отсортировать по нему.

Ваш документ будет выглядеть так:

{'a' : x , 'b' : y, c : z} // z = x/y

И вы будете сортировать по 'c':

find().sort({c : 1})
1 голос
/ 24 февраля 2011

Я не верю, что это возможно, поскольку вы также не можете запускать запросы, сравнивающие 2 поля (без использования $ где для указания функции javascript, которая будет медленной). Вместо этого я подозреваю, что вам нужно также хранить соотношение отдельно в документе, а затем сортировать по этому новому полю.

0 голосов
/ 25 февраля 2011

Точно так же, как сказал Bugai13, вам нужно третье свойство в вашей коллекции, чтобы выполнить сортировку.Вы можете добавить свойство ratio с помощью вызова mapReduce (как показано ниже), но это не будет очень быстро для больших коллекций - и заблокирует вашу базу данных, пока она работает.Вы действительно должны вручную поддерживать свойство ratio - это не должно быть очень сложно.

db.data.insert({a: 1, b: 1});
db.data.insert({a: 2, b: 2});
db.data.insert({a: 3, b: 3});
db.data.insert({a: 1, b: 4});
db.data.insert({a: 2, b: 1});
db.data.insert({a: 3, b: 2});
db.data.insert({a: 1, b: 3});
db.data.insert({a: 2, b: 4});
db.data.insert({a: 3, b: 1});
db.data.insert({a: 1, b: 2});
db.data.insert({a: 2, b: 3});
db.data.insert({a: 3, b: 4});

db.data.mapReduce(
    function(){
        emit(this._id, this);
    },
    function(k, vs){
        v = vs[0];
        v.c = v.a / v.b;
        return v;
    },
    {out : 'data'}
);

db.data.find().sort({c:1});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...