【问题标题】:How to automatically send user data to mongo DB如何自动将用户数据发送到 mongo DB
【发布时间】:2017-03-21 22:08:43
【问题描述】:

每次用户连接到应用程序时,我都会使用 socket.io 广播地理定位(lat、lng)并在地图上设置新的标记图标。如果日本的用户连接,socket.io 会将他的位置发送给我,他也会收到我的位置。问题是我不希望用户接收距离很远的用户的位置(并将我的位置发送给),但只能在预定义的半径内(例如:20 公里)。

mongo DB 中的空间搜索似乎适合识别位于同一区域的用户并将其分配给 groupId。相同 groupId 的用户将被分配一个他们将收听的公共 socket.io 频道。

为了实现我的梦想,我实际上是在尝试使用 mongoose 将用户信息推送到 Mongo DB 中。问题是猫鼬在服务器中运行,而数据在客户端。

我已经定义了一个 schema.js 来构建数据库,但是我对如何设置将客户端数据与 mongoose 链接的路由有点迷茫?我知道猫鼬和客户端都必须返回适当的 JSON 对象才能进行通信,并且可以使用 model.save() 存储数据。很抱歉这个幼稚的问题,但在这一点上的帮助将不胜感激。谢谢。

编辑:

我终于使用 socket.io 通过send2DB 函数将用户数据传递给服务器,但我遇到了这个错误:

Object { _id: 50fc08aebb97d3201d000001,
coords; [],
date: Sun Jan 20 2013 16:18:34 GMT+0100 (Paris, Madrid) } has no methode 'push'`

这似乎是数组coords 的问题,但我不明白为什么它也返回日期! 这是代码:

application.js:

    // generate unique user id
    var userId = Math.random().toString(16).substring(2,15);

    // code here
    onLocationfound = function(e){
        userMarker.setLatLng(e.latlng);
        map.setView(userMarker.getLatLng(),map.getZoom()); 
        latitude = (e.latlng[0]||( Math.round(e.latlng.lat*1000)/1000));
        longitude = (e.latlng[1]||( Math.round(e.latlng.lng*1000)/1000));

    // send data to database (executed once)
    sentData = {id: userId, coords: [{lat: latitude, lng: longitude}]}
    socket.emit('send2DB', sentData);

server.js:

mongoose.connect('mongodb://localhost/test');

var mongoose = require('mongoose')
    , Schema = mongoose.Schema
    , ObjectId = Schema.ObjectId;

// create schema
var userInformation = new Schema({
    username: { type: String, required: true, trim: true },
    email: { type: String, required: true, trim: true },
    role: { type: String, required: true, trim: true },
    date: {type: Date, default: Date.now},
    userId: String,
    longitude: Number,
    latitude: Number,
    coords: [Number, Number]
});

// export retrieve my model

var MyModel = mongoose.model('ModelName', userInformation);
var instance = new MyModel();

// code here

io.sockets.on('connection', function (socket) {

// code here

// Store user data to DB then query spatial info //
socket.on('send2DB', function (data) {

    console.log('Position is', data);
    instance.push(
        {userId: 'data.id'},
        {latitude: 'data.lat'}
        );
    instance.save(function (err) {
      if (!err) console.log('Success!')
      else console.log('Error');
    });

});

【问题讨论】:

  • 您需要在连接中编写一些代码,以便 socket.io 使用会话或其他令牌跟踪特定用户。然后随着新数据的到来,在服务器上为特定事件编写一个带有地理数据的处理程序以更新位置。您只是在为您的客户端应用程序编写一个 API 层来调用。客户端不会(也不应该)直接调用数据库。
  • 我已经用新的代码和结果更新了我的帖子。总而言之,一旦找到用户的位置,我就会尝试存储数据。然后我会查询一些空间信息来识别他周围的用户。你可以看看我的错误吗?谢谢

标签: javascript node.js mongodb express mongoose


【解决方案1】:

我认为您通常走在正确的道路上。以下是几个容易注意到的问题:

  1. push 方法从何而来? (您没有任何数组)
  2. 您不想在从客户端接收到新数据时在 MyModel 的新实例上设置属性吗?
  3. 我认为您应该在套接字检索到 send2DB 数据时创建一个新的 MyModel。然后,只需设置属性。
  4. 另外,您不想让userId 引用字符串'data.id',是吗?你不只是想要价值,就像userId: data.id一样吗? (因为您可能想要来自套接字 data 对象的值)

基础知识可以在猫鼬docs 中找到。 .

socket.on('send2DB', function(data) {
    var instance = new MyModel({userId: data.id, latitude: data.lat});
    instance.save(function(err, instance) { /* callback */ });
});

最终,您可能希望为您的 API 函数添加一些安全性等,而不仅仅是相信 User.id 是有效的和位置。

【讨论】:

  • 谢谢 WiredPrairie。 1.你说得对push在这里不合适。 2. 这正是我想要的。 3. 我现在明白了。 4. 那是我的错误。正如您建议的那样,一旦调用send2DB,我就会创建我的模型。 if (!err) console.log('Success!') else console.log(instance); 告诉我发生了错误并且实例未定义。我应该添加你提到的 Express 和 socket.io session 的安全性吗?交易
  • @floflo 是的,我会通过 Express 和 socket.io 添加安全性。
  • function(err, instance) 中添加实例回调的目的是什么?因为没有它它不会报告错误,就像这样:instance.save(function (err) {if (err) { console.log(err); } else console.log('Information added to the database');});
  • 如果您使用的是闭包,则没有必要。但是,这是 mongoose 文档显示的内容,所以为了完整起见,我将其包含在内。
  • 我已将 userId 设置为 index: {unique: true} 以避免在用户位置更改时重复用户。我无法使用.update 处理这种情况,$exists: true.save 都不会返回错误。无论如何,我会尝试查看代码。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 2021-12-27
  • 2014-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多