2016-03-14 2 views
0

Я новичок в mongodb & mongoose, чем больше я ищу в документации по мангуста, тем больше теряюсь.
говорят, у меня есть user, который это name поле имеет значение Джон, Джон два role S:как получить только «уникальный» субдокумент в мангусте, удалив дубликаты?

  • привилегированного
  • администратора

каждый из этих role с имеет некоторые permissions :

  • суперпользователя
    • addQuestion
    • editQuestion
    • removeQuestion
  • Админ
    • addQuestion
    • viewAnswer

, как вы видите, есть дубликаты для каждого role, как я могу получить права доступа пользователя Джон в массиве без дубликатов (повторное один в этом примере addQuestion), как это:

[ 'addQuestion », 'editQuestion', 'removeQuestion', 'viewAnswer']

это моя схема:

var mongoose = require('mongoose'); 
var Schema = mongoose.Schema; 
var deepPopulate = require('mongoose-deep-populate')(mongoose); 

var UserSchema = new Schema({ 
    name: String, 
    user_roles: [{ 
     type: Schema.ObjectId, 
     ref: 'Role' 
    }] 
}); 

var RoleSchema = new Schema({ 
    name: String, 
    permissions: [ 
     { 
      type: Schema.ObjectId, 
      ref: 'Permission' 
     } 
    ] 
}); 

var PermissionSchema = new Schema({ 
    name: String 
}); 


UserSchema.plugin(deepPopulate, { 
    whitelist: ['user_roles.permissions'] 
}); 

var User = mongoose.model('User', UserSchema), 
Role = mongoose.model('Role', RoleSchema), 
Permission = mongoose.model('Permission', PermissionSchema); 

, как вы видите, я не имена разрешения в permissions, у меня есть ссылки (ObjectId).

У меня только userId пришел с URL. так:

User.findById(userId) 
    .deepPopulate('user_roles') 
    .deepPopulate('user_roles.permissions') 
    .distinct('permissions') 
    .distinct('user_roles.permissions') 
    .exec((err, user)=> { 
     if(err) res.send(err); 
     ???? 
     res.json(permissionsArr); 
    }); 

я должен использовать distinct? Могу ли я использовать distinct без populate Сначала? или это необходимо? или вместо distinct я должен использовать user элемент, переданный в функцию обратного вызова и вместо ???? использовать параметр user (используя метод find), чтобы получить все роли, и все роли получают разрешения, а затем удаления дубликатов из массива permissionsArr?

UPDATE: это результат отдыха апи я сделал с помощью мангуста, получая роли пользователя (GET http://localhost/api/users/:userId/roles):

app.get('/api/users/:userId/roles', function(req,res) { 
    User.findById(req.params.userId) 
     .deepPopulate('user_roles.permissions') 
     .select('user_roles') 
     .exec((err, users)=> { 
      if(err) next(err); 
      res.json(users); 
     }); 
} 

результат:

{ 
    "name": "John", 
    "_id": "56e677c1a7e7007d5cc245ef", 
    "user_roles": [ 
     { 
      "_id": "56e64f057e8008263dec2cc9", 
      "name": "superuser", 
      "permissions": [ 
       { 
        "name": "removeQuestion", 
        "_id": "56e408a9d863a8cf4d7ab001" 
       }, 
       { 
        "name": "addQuestion", 
        "_id": "56e64d657e8008263dec2cc4" 
      }, 
      { 
        "name": "addAnswer", 
        "_id": "56e64cf87e8008263dec2cc3" 
      }, 
      { 
        "name": "viewQuestion", 
        "_id": "56e64e1e7e8008263dec2cc5" 
      }, 
      { 
        "name": "viewAnswer", 
        "_id": "56e64e267e8008263dec2cc6" 
      } 
      ] 
    }, 
    { 
      "_id": "56e64ec27e8008263dec2cc8", 
      "name": "admin", 
      "permissions": [ 
       { 
        "name": "addQuestion", 
        "_id": "56e64d657e8008263dec2cc4" 
       }, 
       { 
        "name": "addAnswer", 
        "_id": "56e64cf87e8008263dec2cc3" 
       }, 
       { 
        "name": "viewQuestion", 
        "_id": "56e64e1e7e8008263dec2cc5" 
       }, 
       { 
        "name": "viewAnswer", 
        "_id": "56e64e267e8008263dec2cc6" 
       } 
      ] 
     } 

теперь, что мне нужно, чтобы GEThttp://localhost/api/users/:userId/permissions и тем самым получить permissions из roles, что пользователь имеет, но с дубликатами был удален. (user не должен иметь permissions dire ctly.)

спасибо за ваше время и за любую помощь, которую вы можете предоставить.

+0

Я предлагаю вам обновить сообщение с образцами документов с дублированием от MongoDB. – Saleem

+0

Я не знаю, как заполнить после запроса в оболочке mongodb, но я предоставил JSON, возвращающийся из моего rest api, содержащего дубликаты. было бы очень приятно, если бы вы дали подсказку @Saleem. Спасибо. :) – asedsami

ответ

1

После тестирования некоторых кодов с вашей схемой, я считаю .distinct только отчетливое значение user_roles, а не результат populate, такое, как user_roles.permissions. Здесь может быть один способ удалить дубликат permissions после заполнения через фильтрацию результата пользователя.

User.findById('56e7b1f74e7192381adbfdbc') 
    .populate({ 
     path: 'user_roles', 
     model: 'Role', 
     populate: { 
      path: 'permissions', 
      model: 'Permission'   
     } 
    }) 
    .exec(function(err, user) { 
     if (err) 
      console.log(err); 
     else { 
      //console.log(util.inspect(user, { showHidden: true, depth: null })); 

      var s = new Set(); 
      // remove duplicate permission 
      user.user_roles.forEach(function(u){ 
       u.permissions.forEach(function(p) { 
        s.add(p.name); 
       }) 
      }) 

      var arr = [...s]; // convert set to array 
      console.log(arr); 
     } 
    }); 

Кстати, вы можете заполнить гнездо результат, таким образом, без использования модуля mongoose-deep-populate.

+0

Я не знал о 'Set()' и nest populate, я попробую его сегодня, большое спасибо ... – asedsami

+1

@asedsami, 'Set()' является новым для ES6, который может поддерживаться в последней версии node.js. – zangw

+0

Извините, почему гнездо, которое вы упомянули, не находится в документации по мангуста? Я не видел его нигде, кроме Stackoverflow. – asedsami

0

Действительно, вы можете отключить свой вложенный массив разрешений, используя структуру агрегации. У вас также есть опция уменьшения карты, но структура агрегации рекомендуется и более эффективна.

db.users.aggregate([ 
    {$match:{_id:"56e677c1a7e7007d5cc245ef"}}, 
    {$unwind:"$user_roles"}, 
    {$unwind:"$user_roles.permissions"}, 
    {$group:{_id:"$_id", permissions:{$addToSet:"$user_roles.permissions.name"}}} 
]) 

На основе вашего образца документа, он должен принести

{ 
    "_id" : "56e677c1a7e7007d5cc245ef", 
    "permissions" : [ 
     "addAnswer", 
     "viewAnswer", 
     "viewQuestion", 
     "addQuestion", 
     "removeQuestion" 
    ] 
} 

Я уверен, вы можете перевести его в мангуста, и это довольно легко.

Смежные вопросы