2016-01-06 58 views
0

我正在制作anroid应用程序并使用express作为后端。 这是我快递男孩架构在mongodb中更改客户端时更新位置

var DeliveryBoySchema = new Schema({ 

    name: String, 
    college: {type:String}, 
    password: {type: String, required: true, select: false}, 
    lat:{type: String}, 
    long:{type:String} 

}); 

当送货员改变它的位置,它就会在MongoDB的更新。 因此,查看此送货员的用户(即客户)正在跟踪他的位置。我发现有两种方法可以做到这一点:

。客户端每5秒调用一次api并获取送货员的当前位置。

。我发现了另一个有趣的方法来做到这一点,即使用套接字。

我不是很清楚它的功能。当数据库发生更改并且用户看到当前位置时,我遇到了如何更新客户端的问题。

回答

0

解决方案1不好,只是因为您的服务器会臃肿,无法及时响应。忘掉这个:)简单地说,应该从你的服务器只查询一次位置,第一次加载应用程序。

你可能会认为送货员是一个游戏。假设为了简单起见,只有一个玩家和几个观众。玩家是触发更新位置的玩家。观众只能跟踪更改。本质上,玩家和观众在同一个房间里,这意味着他们,只有在发生变化时才应该更新他们。

  • 但从玩家角度,这是很简单的,他是唯一一个谁可以影响的位置,可以同时向服务器更新送外卖的位置和改变你的观点立场。这里没有问题。每当你的玩家改变送货员的位置时,你都必须坚持存储更新。
  • 从观众的角度来看。每当位置更新发生在数据存储器中时,您需要通知连接到房间的每个人关于位置的变化。有很多方法可以解决这个问题。但最有可能,你将不得不使用一个插座或其他方式(除了一些XMPP客户端解决方案,这要复杂得多)

简单地说,关键是要选对通信信道。就我个人而言,我会使用redis来存储位置,创建订阅频道并通过频道向套接字发布更新。一旦位置更新,您将持续更新redis中的位置,将更改发布到频道(通过队列),通过订阅消费更改,并通过套接字将更新传递给所有侦听客户端。 为什么redis? 1.适用于分布式系统(可扩展)2. PUB/SUB是一个队列,无需获得试图同步的癌症3.PUB/SUB持久4.实际上比纯数据库解决方案(与MongoDB相比)更快

+0

其实,我几乎完成了我的应用程序。这件事剩下了。如果你告诉我如何将它与mongodb和node结合使用会很棒,js – Nkav

+0

有一个用于该https://github.com/NodeRedis/node_redis的库 – Yerken

+0

我希望将它与mongodb和node js一起使用,找到解决办法。 – Nkav

3

根据OP的要求,仅使用mongoose,nodeJSsocket进行编码。实际执行并不一定完全相同,但以下内容应提供有关如何处理和填补缺失差距的总体思路。为了方便起见,我将仅使用ES6功能。

nodeJS版本4.2.2,socket.io 1.3。5,猫鼬版4.1.2,表达4.13.3

  1. 创建一个Socket - 服务器端

//the following is probably your app.js 
 
import express from 'express' 
 
... 
 
var app = express(); 
 
var server = http.createServer(app); 
 
... 
 

 
var socketio = require('socket.io')(server, { 
 
    path: '/socket.io-path, //modify this as per your needs 
 
}); 
 
//now register created socket object 
 
require('./components/socket')(socketio); 
 

 
... 
 
//start the server

//the following is components/socket/index.js 
 

 
function onConnect(socket){ 
 
    //register listeners on mongo schema changes 
 
    require('../../models/deliveryBoy.socket').register(socket); 
 
} 
 

 
module.exports = function(socketio){ 
 
    socketio.on('connection', function(socket) { 
 
    socket.address = socket.request.connection.remoteAddress + 
 
     ':' + socket.request.connection.remotePort; 
 
    //address, e.g. 127.0.0.1:52243 
 

 
    socket.connectedAt = new Date(); 
 
    socket.log = function(...data) { 
 
     console.log(`SocketIO ${socket.address}`, ...data); 
 
    }; 
 
    // Call onDisconnect. 
 
    socket.on('disconnect', function() { 
 
     socket.log('Disconnected: '); 
 
     //do something when user disconnects 
 
    }); 
 

 
    // Call onConnect. 
 
    onConnect(socket); 
 
    socket.log('New connection: '); 
 
    }); 
 
};

  • 附加钩上猫鼬架构定义
  • //this is to be stored at ./models/deliveryBoy.model 
     
    
     
    'use strict'; 
     
    
     
    var mongoose = require('bluebird').promisifyAll(require('mongoose')); 
     
    var Schema = mongoose.Schema; 
     
    
     
    var DeliveryBoySchema = new Schema({ 
     
        name: String, 
     
        college: {type:String}, 
     
        password: {type: String, required: true, select: false}, 
     
        lat:{type: String}, 
     
        long:{type:String} 
     
    }); 
     
    
     
    //attach a hook to be triggered every time you modify the document 
     
    //has to be inserted before the mongoose model is created !!! 
     
    //with !!!ATTENTION!!! update method using $set 
     
    //for example DeliveryBoy.update({_id:'blah'}, {$set: {long: 1, lat: 0}}); 
     
    DeliveryBoySchema.post('update', function(){ 
     
    \t var update = this._update; 
     
    \t if (update.$set && (update.$set.lat || update.$set.long)){ 
     
    \t \t try{ 
     
    \t \t \t var updatedObjectId = this._conditions._id; //will serve as a room 
     
          var newLoc = { 
     
           lat: update.$set.lat, 
     
           long: update.$set.long 
     
          } 
     
    \t \t \t //now emit the event using nodejs event emitter 
     
    
     
          require('../../components/app.events').emit('updateLoc', {roomId: updatedObjectId, newLoc: newLoc}); 
     
    \t \t } 
     
    \t } 
     
    }); 
     
    
     
    module.exports = mongoose.model('DeliveryBoy', DeliveryBoySchema);

  • 插槽监听器DeliveryBoy
  • //this is the component which implement socket specifically for delivery boy model 
     
    //it is called (register method) from general components/socket module 
     
    
     
    exports.register = function(socket){ 
     
        AppEvents.on('updateLoc', function(socket){ 
     
        return function(info){ 
     
         socket.to(info.roomId).emit('newLocation', info.newLoc); 
     
        } 
     
        }); 
     
    }

  • 现在你只需要连接到基于该deliveryboy ID从客户端的房间,并使用来自客户端的消息,并更新你的视图相应
  • 还有一件事,你这是怎么从你的REST API更新数据库

    app.put('/update/:gameId', function(req, res){ 
     
        DeliveryBoy.update({_id: req.params.gameId}, {$set: req.body}, function(err){ 
     
         res.send(200); //of course this needs to be handled properly, but i am too tired after typing all these 
     
         //you owe me couple beers dude 
     
    }); 
     
    });

    P.S该代码有点麻烦,但你应该能够做出相应的改进。如果有任何问题让我知道。但基本的概念应该清楚

    +0

    Thnaks很多人! :) – Nkav