Сбор заказов по нескольким полям и условиям в Mongoid - PullRequest
0 голосов
/ 04 мая 2018

У меня есть 4 поля в документе, которые name, online, like и score. Я хочу упорядочить по нескольким полям и условиям сбор миллионов документов с нумерацией страниц.

Пример некоторых документов:

Мои пользовательские документы:

{ "_id": 1, "name": "A", "online": 1, "like": 10, "score": 1 },
{ "_id": 2, "name": "B", "online": 0, "like": 9, "score": 0 },
{ "_id": 3, "name": "C", "online": 0, "like": 8, "score": 1 },
{ "_id": 4, "name": "D", "online": 1, "like": 8, "score": 0 },
{ "_id": 5, "name": "E", "online": 1, "like": 7, "score": 1 },
{ "_id": 6, "name": "F", "online": 0, "like": 10, "score": 0 },

Я объясню свою точку зрения на следующем примере (пример с использованием массива).

Пример на языке ruby, у меня структура массива выглядит так:

[["A", 1, 10, 1],
["B", 0, 9, 1],
["C", 0, 8, 1],
["D", 1, 8, 0],
["E", 1, 7, 1],
["F", 0, 10, 0]]

Если online равно 1, то следует выполнить повторную сортировку по убыванию like, но когда online имеет значение 0, следует выполнить повторную сортировку по убыванию score.

.

пример сортировки:

list.sort{|a, b| a[1] == 1 ? ([-a[1], -a[2]] <=> [-b[1], -b[2]]) : ([-a[1], -a[3]] <=> [-b[1], -b[3]]) }

Результат такой:

[["A", 1, 10, 1],
["D", 1, 8, 0],
["E", 1, 7, 1],
["B", 0, 9, 1],
["C", 0, 8, 1],
["F", 0, 10, 0]]

Это сортировка по массиву, но моя проблема в том, что у меня есть коллекция mongodb и миллион документов, я не могу использовать сортировку по массиву, потому что это приведет к большой нагрузке на базу данных, должно получить все документы и преобразовать в массив (включая сортировку ) и чем их разбивают на страницы, я думаю, что это плохая идея.

Я пытаюсь использовать дополнительный метод order() / order_by() mongoid, например:

User.
order_by([:online, :desc], [:like, :desc], [:score, :desc]).
hint(online: -1, like: -1, score: -1).
page(1).per(10)

Но этот запрос имеет порядок только по online и score, есть ли метод сортировки в mongoid, как сортировка массива? или в mongodb есть что-то вроде пузырьковой сортировки?

та же проблема здесь: Ruby on Rails: объединение результатов Mongoid критериев и подкачки , merge метод не помог мне, потому что он может заменить первый критерий.

Ответы [ 2 ]

0 голосов
/ 11 мая 2018

Предполагая, что значения полей, как и онлайн, являются числовыми, исходя из условия, мы можем создать вспомогательное поле, которое представляет собой сумму онлайн и лайков или онлайн и счет. После чего мы можем отсортировать новое поле и любое другое обязательное поле.

db.collection aggregate([ {"$addFields": {"refCount":{"$cond":{"if":{"$eq":["$online", 1]}, "then":{"$add": ["$online", "$like"]}, "else": {"$add": ["$online", "$score"]} } } }},{ "$sort": { "refCount": -1 ,"id":1} },{"$project":{"id": 1, "name": 1, "online": 1, "like": 1,"score":1}},{ "$limit": 10 } ])

На первом этапе конвейера строят вспомогательные поля refcount . Это поле затем используется в $ sort вместе с id . На следующем этапе у нас есть проекция обязательных полей с последующим предложением limit. Вместо числовых, если бы эти поля были строками, потребовалось бы дополнить конкатенацию полей.

0 голосов
/ 07 мая 2018

Использование агрегации $cond

User.collection.aggregate([
      { 
        "$project" => {
            "id" => 1, 
            "name" => 1, 
            "online" => 1, 
            "like" => 1, 
            "score" => 1,
            "sort" => {
                "$cond" => {
                   "if" => { 
                      "$eq" => ["$online", 1] 
                   },
                   "then" => "$like",
                   "else" => "$score"
                }
            }
       }
     },
     { 
        "$sort" => {
            "online" => -1,  
            "sort" => -1,
            "id" => 1
        }
     },
     {
        "$skip" => 0
     { 
        "$limit" => 12 
     }
])

ссылки:

  1. https://docs.mongodb.com/manual/reference/operator/aggregation/cond/
  2. https://www.oodlestechnologies.com/blogs/How-to-use-Conditional-Statements-for-sorting-data-in-MongoDB
...