Как получить данные, основанные на значениях подполей в mongodb, используя mon goose? - PullRequest
3 голосов
/ 07 апреля 2020

У меня есть случай, когда мне нужно найти данные о роли и разрешениях из MongoDB на основе значения parent.

Вот пример данных.

{
    "_id" : ObjectId("5e8c0dea360c754568906611"),
    "locations" : {
        "canCreate" : true,
        "canView" : true,
        "canUpdate" : true,
        "canDelete" : true,
        "isMenu" : false,
        "parent" : "settings"
    },
    "assets" : {
        "canCreate" : true,
        "canView" : true,
        "canUpdate" : true,
        "canDelete" : true,
        "isMenu" : true,
        "parent" : "assets"
    },
    "tickets" : {
        "canCreate" : true,
        "canView" : true,
        "canUpdate" : true,
        "canDelete" : true,
        "isMenu" : true,
        "parent" : "tickets"
    },
    "settings" : {
        "canCreate" : true,
        "canView" : true,
        "canUpdate" : true,
        "canDelete" : true,
        "isMenu" : true,
        "parent" : "settings"
    },
    "user_management" : {
        "canCreate" : true,
        "canView" : true,
        "canUpdate" : true,
        "canDelete" : true,
        "isMenu" : true,
        "parent" : "user_management"
    },
    "reports" : {
        "canCreate" : true,
        "canView" : true,
        "canUpdate" : true,
        "canDelete" : true,
        "isMenu" : true,
        "parent" : "reports"
    },
    "dashboard" : {
        "canCreate" : true,
        "canView" : true,
        "canUpdate" : true,
        "canDelete" : true,
        "isMenu" : true,
        "parent" : "dashboard"
    },
    "ticketPriorities" : {
        "canCreate" : true,
        "canView" : true,
        "canUpdate" : true,
        "canDelete" : true,
        "isMenu" : false,
        "parent" : "settings"
    },
    "ticketStatus" : {
        "canCreate" : true,
        "canView" : true,
        "canUpdate" : true,
        "canDelete" : true,
        "isMenu" : false,
        "parent" : "settings"
    },
    "users" : {
        "canCreate" : true,
        "canView" : true,
        "canUpdate" : true,
        "canDelete" : true,
        "isMenu" : false,
        "parent" : "user_management"
    },
    "permissions" : {
        "canCreate" : true,
        "canView" : true,
        "canUpdate" : true,
        "canDelete" : true,
        "isMenu" : false,
        "parent" : "user_management"
    },
    "companySettings" : {
        "canCreate" : true,
        "canView" : true,
        "canUpdate" : true,
        "canDelete" : true,
        "isMenu" : true,
        "parent" : "companySettings"
    },
    "customFields" : {
        "canCreate" : false,
        "canView" : false,
        "canUpdate" : false,
        "canDelete" : false,
        "isMenu" : false,
        "parent" : "settings"
    },
    "roleName" : "SUPERUSER",
}

Теперь я хочу получить поля (разрешения), чьи parent, settings и isMenu равны false.

Вот мой запрос, который я использовал до сих пор.

menuName = "settings";

UserRoles.find({"_id":roleId},{menuName:1});

Но я не могу получить данные с помощью моего запроса, и я немного запутался, как получить это. Пожалуйста, рассмотрите мой запрос и предложите мне, как найти решение.

Ответы [ 3 ]

2 голосов
/ 07 апреля 2020

вы можете использовать $objectToArray

db.getCollection('Test07').aggregate([
    { $project: {  permissions : { $objectToArray: "$$ROOT" } } }, 
    { $unwind:"$permissions"},
    { $match: { "permissions.v.parent" : "settings", 
                "permissions.v.isMenu" : false } }, 
])
2 голосов
/ 07 апреля 2020

У меня с этим сработало. дать ему шанс.

db.getCollection('test').find({ "settings.isMenu": true }, { settings: 1})

Вывод:

/ * 1 * /

{
    "_id" : ObjectId("5e8c0dea360c754568906611"),
    "settings" : {
        "canCreate" : true,
        "canView" : true,
        "canUpdate" : true,
        "canDelete" : true,
        "isMenu" : true,
        "parent" : "settings"
    }
}

или если ваша коллекция разрешений имеет только одну запись со всеми разрешениями, то проще всего будет просто Фильтрация необходимых данных с помощью функции, например _.filter от loda sh.

что-то вроде этого;

const menu = "settings"
const list = _.filter(data[0], {parent: menu, isMenu: false});

Вывод:

[ { canCreate: true,
    canView: true,
    canUpdate: true,
    canDelete: true,
    isMenu: false,
    parent: 'settings' },
  { canCreate: true,
    canView: true,
    canUpdate: true,
    canDelete: true,
    isMenu: false,
    parent: 'settings' },
  { canCreate: true,
    canView: true,
    canUpdate: true,
    canDelete: true,
    isMenu: false,
    parent: 'settings' },
  { canCreate: false,
    canView: false,
    canUpdate: false,
    canDelete: false,
    isMenu: false,
    parent: 'settings' } ]
1 голос
/ 07 апреля 2020

Вам нужно попробовать это с mongodb-aggregation-pipe :

db.collection.aggregate([
  /** Retrieve required doc by filtering, will get one doc out */
  {
    $match: {
      _id: ObjectId("5e8c0dea360c754568906611"),
    },
  },
  {
    $project: {
      data: {
        $arrayToObject: {
          $reduce: {
            input: { $objectToArray: "$$ROOT" }, // Convert retrieved doc into an array [{k:...,v:...},{k:...,v:...}] for iteration
            initialValue: [], /** Initial value is [] */
            in: {
              $concatArrays: [
                "$$value", /** Concatinate accumulator with new values */
                {
                  $cond: [
                    {
                      $or: [
                        { $eq: ["$$this.k", "_id"] },
                        { $eq: ["$$this.k", "roleName"] },
                      ],
                    },
                    ["$$this"], /** If k == _id || roleName just add these objects to holding array */
                    {
                      $cond: [
                        {
                          $and: [
                            { $eq: ["$$this.v.isMenu", false] },
                            { $eq: ["$$this.v.parent", "settings"] },
                          ],
                        },
                        ["$$this"], /** If required criteria matches just add these objects to holding array */
                        [], /** If not, add empty array */
                      ],
                    },
                  ],
                },
              ],
            },
          },
        },
      },
    },
  },
  /** Replace newly formed 'data' field as root of document */
  {
    $replaceRoot: {
      newRoot: "$data",
    },
  },
]);

Тест: MongoDB-Playground

Примечание: Не забудьте преобразовать входящий roleId в ObjectId(), чтобы он соответствовал типу _id в БД - который первоначально мог бы string, Проверить convert- строка-ObjectID-в-MongoDB .

...