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

Problemas de estrutura de agregação SailsJS e MongoDB com consultas personalizadas


Sua primeira consulta estava no caminho certo, você estava usando o operador de pipeline errado.
Artist.native(function(err,collection) {

    collection.aggregate(
        [
            { "$project": {
                "_id": 1,
                "name": 1,
                "total": { "$size": "$dubs" }
            }}
        ],
        function(err,result) {
          if (err) return res.serverError(err);
          console.log(result);
        }
})

Claro que o $size O operador requer que você precise de uma versão do MongoDB 2.6 ou superior, o que você provavelmente deve fazer agora, mas ainda pode fazer a mesma coisa sem o operador para medir o comprimento do array:
Artist.native(function(err,collection) {

    collection.aggregate(
        [
            { "$project": {
                "_id": 1,
                "name": 1,
                "dubs": {
                    "$cond": [
                       { "$eq": [ "$dubs", [] ] },
                       [0],
                       "$dubs"
                    ]
                }
            }},
            { "$unwind": "$dubs" },
            { "$group": {
                "_id": "$_id",
                "name": { "$first": "$name" },
                "total": { 
                    "$sum": {
                        "$cond": [
                            { "$eq": [ "$dubs", 0 ] },
                            0,
                            1
                        ]
                    }
                }
            }}
        ],
        function(err,result) {
          if (err) return res.serverError(err);
          console.log(result);
        }
})

Isso faz a mesma coisa contando os membros da matriz, mas, em vez disso, você precisaria $unwind os elementos do array para contá-los. Portanto, ainda pode ser feito, mas não é tão eficiente.

Além disso, você precisa lidar com os casos em que a matriz está realmente em branco, mas presente devido à forma como $unwind trata um array vazio [] . Se não houvesse conteúdo, o documento que continha tal elemento seria removido dos resultados. De forma semelhante, você precisaria usar $ ifNull para definir uma matriz em que o documento nem mesmo continha um elemento para $unwind para não resultar em erro.

Realmente, se você pretende fazer esse tipo de consulta regularmente, deve manter um campo "total" no documento em vez de tentar calculá-lo primeiro. Use o $inc operador junto com operações como $push e $pull para manter uma contagem do comprimento atual da matriz.

Isso se afasta um pouco da filosofia geral do Waterline, mas você já introduziu operações de agregação nativa e não é muito difícil perceber que você está obtendo melhor desempenho usando operações nativas em outras áreas também.

Então, com documentos como estes:
{
  "dubs": [{},{},{}],
  "name": "The Doors",
  "createdAt": "2014-12-15T15:24:26.216Z",
  "updatedAt": "2014-12-15T15:24:26.216Z",
  "id": "548efd2a436c850000353f4f"
},
{
  "dubs": [],
  "name": "The Beatles",
  "createdAt": "2014-12-15T20:30:33.922Z",
  "updatedAt": "2014-12-15T20:30:33.922Z",
  "id": "548f44e90630d50000e2d61d"
}

Você obtém exatamente os resultados que deseja em cada caso:
{
    "_id" : ObjectId("5494b79d7e22da84d53c8760"),
    "name" : "The Doors",
    "total" : 3
},
{
    "_id" : ObjectId("5494b79d7e22da84d53c8761"),
    "name" : "The Beatles",
    "total" : 0
}