MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Mongo Ordenar por Contagem de Partidas na Matriz


Para realmente responder isso primeiro, você precisa "calcular" o número de correspondências para a condição dada para "ordenar" os resultados para retornar com a preferência para a maioria das correspondências no topo.

Para isso você precisa do framework de agregação, que é o que você usa para "cálculo" e "manipulação" de dados no MongoDB:
db.multiArr.aggregate([
  { "$match": { "Keys": { "$in": [ "carrot", "banana" ] } } },
  { "$project": {
    "ID": 1,
    "Keys": 1,
    "order": {
      "$size": {
        "$setIntersection": [ ["carrot", "banana"], "$Keys" ]
      }
    }
  }},
  { "$sort": { "order": -1 } }
])

Em um MongoDB anterior à versão 3, você pode fazer a forma mais longa:
db.multiArr.aggregate([
  { "$match": { "Keys": { "$in": [ "carrot", "banana" ] } } },
  { "$unwind": "$Keys" },
  { "$group": {
    "_id": "$_id",
    "ID": { "$first": "$ID" },
    "Keys": { "$push": "$Keys" },
    "order": {
      "$sum": {
        { "$cond": [
          { "$or": [
           { "$eq": [ "$Keys", "carrot" ] },
           { "$eq": [ "$Keys", "banana" ] }
         ]},
         1,
         0
        ]}
      }
    }
  }},
  { "$sort": { "order": -1 } }
])

Em ambos os casos, a função aqui é primeiro combinar os documentos possíveis com as condições, fornecendo uma "lista" de argumentos com $in . Uma vez que os resultados são obtidos, você deseja "contar" o número de elementos correspondentes na matriz para a "lista" de valores possíveis fornecidos.

Na forma moderna, o $setIntersection O operador compara as duas "listas" retornando uma nova matriz que contém apenas os membros correspondentes "exclusivos". Como queremos saber quantas correspondências foram, simplesmente retornamos o $size dessa lista.

Em versões mais antigas, você separa o array de documentos com $unwind para realizar operações nele, pois as versões mais antigas não possuíam os operadores mais recentes que trabalhavam com arrays sem alterações. O processo então examina cada valor individualmente e se qualquer expressão em $or corresponde aos valores possíveis, então o $cond ternário retorna um valor de 1 para o $sum acumulador, caso contrário 0 . O resultado líquido é a mesma "contagem de partidas" mostrada na versão moderna.

A última coisa é simplesmente $sort os resultados com base na "contagem de correspondências" que foi retornada para que a maioria das correspondências fique no "topo". Esta é uma "ordem decrescente" e, portanto, você fornece o -1 para indicar isso.

Adendo sobre $in e arrays


Você está entendendo mal algumas coisas sobre as consultas do MongoDB para iniciantes. O $in na verdade, o operador destina-se a uma "lista" de argumentos como este:
{ "Keys": { "$in": [ "carrot", "banana" ] } }

Que é essencialmente a forma abreviada de dizer "Combine 'cenoura' ou 'banana' na propriedade 'Chaves'" . E poderia até ser escrito em formato longo assim:
{ "$or": [{ "Keys": "carrot" }, { "Keys": "banana" }] }

O que realmente deveria levar você a se fosse uma condição de correspondência "singular", então você simplesmente fornece o valor para corresponder à propriedade:
{ "Keys": "carrot" }

Então isso deve cobrir o equívoco de que você usa $in para corresponder a uma propriedade que é uma matriz em um documento. Em vez disso, o caso "reverso" é o uso pretendido onde, em vez disso, você fornece uma "lista de argumentos" para corresponder a uma determinada propriedade, seja essa propriedade uma matriz ou apenas um valor único.

O mecanismo de consulta do MongoDB não faz distinção entre um valor único ou uma matriz de valores em uma operação de igualdade ou similar.