MongoDB sorting basis of two field. let say if A & B both have value return first then either A and B

44 Views Asked by At

I want to sort the MongoDB document basis on the condition. let say if A & B both have value return this. then return either A or B and after that return null value.

I have written the query & it's working as expected but when I add a limit & skip then it's not working as expected.

db.collection.aggregate([
{
    "$addFields": {
        "hasBothFields": {"$cond": {"if": {"$and": [{"$isArray": "$treasuries"}, {"$isArray": "$tokens"}, {"$gt": [{"$size": "$treasuries"}, 0]}, {"$gt": [{"$size": "$tokens"}, 0]}]}, "then": 1, "else": 0}},
        "hasOnlyA": {"$cond": {"if": {"$and": [{"$isArray": "$treasuries"}, {"$not": {"$isArray": "$tokens"}}, {"$gt": [{"$size": "$treasuries"}, 0]}]}, "then": 1, "else": 0}},
        "hasOnlyB": {"$cond": {"if": {"$and": [{"$not": {"$isArray": "$treasuries"}}, {"$isArray": "$tokens"}, {"$gt": [{"$size": "$tokens"}, 0]}]}, "then": 1, "else": 0}}
    }
},
{
    "$sort": {
        "hasBothFields": -1,
        "hasOnlyA": -1,
        "hasOnlyB": -1
    }
},
{
    "$project": {
        "hasBothFields": 0,
        "hasOnlyA": 0,
        "hasOnlyB": 0
    }
},
// {
//     "$skip": 1
// },
// {
//     "$limit": 10
// }
]);

I added $skip & $limit before & after the $project pipeline & checked. its not returning the correct output.

Here is the demo link

https://mongoplayground.net/p/NaQRr9GUQSi

Correct output:

[
{
  "_id": 1,
  "tokens": {
    "id": 123,
    "name": "xyz"
  },
  "treasuries": [
    {
      "address": "0x7e9e4c",
      "name": "Main",
      "network": "1"
    }
  ]
},
{
  "_id": 2,
  "tokens": null,
  "treasuries": [
    {
      "address": "0x7e9e4c",
      "name": "Main 2",
      "network": "12"
    }
  ]
}
]

But it returning this. "tokens": null on top

[
{
  "_id": 2,
  "tokens": null,
  "treasuries": [
    {
      "address": "0x7e9e4c",
      "name": "Main 2",
      "network": "12"
    }
  ]
},
{
  "_id": 3,
  "tokens": null,
  "treasuries": []
},
{
  "_id": 4,
  "tokens": null,
  "treasuries": null
}
]
1

There are 1 best solutions below

0
Krishna Kumar Yadav On

With the help of the comment mentioned by @cmgchess. I solved this query.

db.collection.aggregate(
[
{
  "$addFields": {
    "hasBothFields": {
      "$cond": {
        "if": {
          "$and": [{
              "$isArray": "$treasuries"
            },
            {
              "$gt": [{
                  "$size": "$treasuries"
                },
                0
              ]
            },
            {
              "$ne": [
                "$tokens",
                null
              ]
            }
          ]
        },
        "then": 1,
        "else": 0
      }
    },
    "hasOnlyA": {
      "$cond": {
        "if": {
          "$and": [{
              "$isArray": "$treasuries"
            },
            {
              "$eq": [
                "$tokens",
                null
              ]
            },
            {
              "$gt": [{
                  "$size": "$treasuries"
                },
                0
              ]
            }
          ]
        },
        "then": 1,
        "else": 0
      }
    },
    "hasOnlyB": {
      "$cond": {
        "if": {
          "$and": [{
              "$not": {
                "$isArray": "$treasuries"
              }
            },
            {
              "$ne": [
                "$tokens",
                null
              ]
            }
          ]
        },
        "then": 1,
        "else": 0
      }
    }
  }
},
{
  "$sort": {
    "hasBothFields": -1,
    "hasOnlyA": -1,
    "hasOnlyB": -1
  }
},
{
  "$project": {
    "hasBothFields": 0,
    "hasOnlyA": 0,
    "hasOnlyB": 0
  }
}
]
)

Here is the working demo link

Working Demo link