Javascript meteor用户未同步配置文件的已发布子字段

Javascript meteor用户未同步配置文件的已发布子字段,javascript,meteor,user-accounts,Javascript,Meteor,User Accounts,在使用我的社交应用程序时,我在Meteor.users集合中发现了一个奇怪的行为。使用相同方法的其他集合不会出现此问题 我想有一个用户下载每个人的最低数量的信息的初始列表,当我打开面板给一个特定的用户,我订阅一个不同的显示更多信息,如果指定的用户是我的朋友 但在订阅客户端集合Meteor.users后,不会更新 客户端 Meteor.startup(function() { Meteor.subscribe('usersByIds', Meteor.user().profile.fri

在使用我的社交应用程序时,我在Meteor.users集合中发现了一个奇怪的行为。使用相同方法的其他集合不会出现此问题

我想有一个用户下载每个人的最低数量的信息的初始列表,当我打开面板给一个特定的用户,我订阅一个不同的显示更多信息,如果指定的用户是我的朋友

但在订阅客户端集合Meteor.users后,不会更新

客户端

Meteor.startup(function() {

    Meteor.subscribe('usersByIds', Meteor.user().profile.friends, function() {

        //... make users list panel using minimal fields

    });

    //performed when click on a user
    function userLoadInfo(userId) {

        Meteor.subscribe('userById', userId, function() {

            var userProfile = Meteor.users.findOne(userId).profile;

            //...
            //make template user panel using full or minimal user fields
            //...

            //BUT NOT WORK!

            //HERE Meteor.users.findOne(userId) keep minial user fields!!
            //then if userId is my friend!

        });         
    }
});
服务器

//return minimal user fields
getUsersByIds = function(usersIds) {

    return Meteor.users.find({_id: {$in: usersIds} },
                            {
                                fields: {
                                    'profile.username':1,
                                    'profile.avatar_url':1
                                }
                            });
};

//return all user fields
getFriendById = function(userId) {

    return Meteor.users.find({_id: userId},
                            {
                                fields: {
                                    'profile.username':1,
                                    'profile.avatar_url':1
                                    //ADDITIONAL FIELDS                         
                                    'profile.online':1,
                                    'profile.favorites':1,
                                    'profile.friends':1
                                }
                            });
};

//Publish all users, with minimal fields
Meteor.publish('usersByIds', function(userId) {

    if(!this.userId) return null;

    return getUsersByIds( [userId] );
});

//Publish user, IF IS FRIEND full fields
Meteor.publish('userById', function(userId) {

    if(!this.userId) return null;

    var userCur = getFriendById(userId),
        userProfile = userCur.fetch()[0].profile;

    if(userProfile.friends.indexOf(this.userId) != -1)  //I'm in his friends list
    {
        console.log('userdById IS FRIEND');
        return userCur;     //all fields
    }
    else
        return getUsersByIds( [userId] );   //minimal fields
});

这是DDP中的一个限制或缺陷。看

一种解决方法是将数据移出
用户.profile

像这样:

//limited publish
Meteor.publish( 'basicData', function( reqId ){
  if ( this.userId ) {      

    return Meteor.users.find({_id: reqId },{
      fields: { 'profile.username':1,'profile.avatar_url':1}
    });
  } 
  else {
    this.ready();
  }
});

//friend Publish
Meteor.publish( 'friendData', function( reqId ){
  if ( this.userId ) {

    return Meteor.users.find( {_id: reqId, 'friendProfile.friends': this.userId }, {
      fields: {
        'friendProfile.online':1, 
        'friendProfile.favorites':1,
        'friendProfile.friends':1
      }
    });
  } 
  else {
    this.ready();
  }
});

//example user
var someUser = {
   _id: "abcd",
   profile: {
     username: "abcd",
     avatar_url: "http://pic.jpg"
   },
   friendProfile: {
     friends: ['bcde', 'cdef' ],
     online: true,
     favorites: ['stuff', 'otherStuff' ]
   }
}
正如在评论中所给出的,链接揭示了您的问题。当前的DDP协议不允许发布子文档。解决这个问题的一种方法是使用数据创建一个单独的集合,但更好的方法可能是删除一些数据,使其成为用户的直接对象

最好的方法是在插入时将数据添加到用户的配置文件中,然后在中直接将数据移动到用户上:

Accounts.onCreateUser(function(options, user) {
    if (options.profile) {
        if (options.profile.publicData) {
            user.publicData = options.profile.publicData;
            delete options.profile.publicData;
        }
        user.profile = options.profile;
    }
    return user;
});

如果允许客户端执行用户插入,请确保更好地验证数据。通过这种方式,您可以在配置文件中设置
联机
收藏夹
、和
朋友
,并在需要时专门发布。然后,您可以将
用户名
化身url
直接放在用户的
publicData
对象中,并始终发布。

您确定在单击按钮时会调用您的完整用户订阅吗?您是否已在控制台中检查以验证数据是否缺失?您可能希望在订阅中使用.ready(),而不是尝试使用回调。是的,我确信因为服务器会打印日志:“userdById IS FRIEND”,但客户端集合不会更新!我试过在publish中使用此.ready(),但不起作用!:(我使用chrome控制台在客户端测试用户Collection Meteor.users.find().fetch()…但数据未使用完整字段更新!我已经尝试过这种方法(双重发布),但如果我在有限发布之前和完全发布之后请求…在Meteor.users(客户端)中,字段仍然有限!订阅工作(我看到日志)但是在本地收集数据中没有更改!我想澄清的是,此问题仅出现在Meteor.users收集中,对于其他收集它可以工作!使用.rewind()不会更改行为:(做了更多的检查。这是一个已知的错误,出于某种原因,它仍然没有记录-。这不仅仅是用户文档,而是子文档的任何发布。因此,解决方法是将您的一些数据移出profile字段。@user728291我认为这本身不是一个错误。只是为了使协议不那么复杂。好的,但是..原因是这件事没有文档记录,我想说这是一种有趣的方式!但这会在客户端Meteor.user()中造成一个大问题不包含字段publicData,但仅包含配置文件!!我认为这是由accounts base package发送的默认字段造成的。我不知道如何解决此问题this@StefanoCudini如果采用这种方法,服务器是否在根目录上包含publicData对象(因此不嵌套在配置文件中)?“我是编辑过的用户”集合(将字段从配置文件移动到publicData),但以这种方式,在客户端Meteor.user中不包含publicData,只包含配置文件empty@StefanoCudini我理解您的问题,但您是否已在服务器上签入mongodb以查看是否保存了数据?是的,我正在使用mongo控制台(用于服务器)和chrome控制台(用于客户端),现在是否可以使用curreUser的自定义发布来解决(包括登录用户的publicData字段和profile字段