Search code examples
node.jsmongoosewebsocketapolloapollo-server

mongoose: continuously save data


I'm trying to save the websocket data as its updated into mongodb and be able to query the data with GQL! I'll have to rework what I have but I'm just a little confused about how to go about this?

Anyways, any help would be appreciated <3

const mongoose = require('mongoose');

mongoose.connect("URI", {
  useNewUrlParser: true,
  useFindAndModify: false,
  useCreateIndex: true,
  useUnifiedTopology: true,
});


const { ApolloServer, PubSub, gql } = require('apollo-server');

const pubsub = new PubSub();

// saves in db as plural eg: btcusdklines ???
const BTCUSDkline = mongoose.model("BTCUSDkline",{
    time: Number,
    open: Number,
    high: Number,
    low: Number,
    close: Number,
});

const typeDefs = gql`
  type Query {
      getBTCUSDkline: [BTCUSDkline]
  }
  type BTCUSDkline {
      id: ID!
      time: Int
      open: Int
      high: Int
      low: Int
      close: Int
  }
`;

const resolvers = {
  Query: {
      getBTCUSDkline: ()=> BTCUSDkline.find(),
  },
}

const server = new ApolloServer({ 
  typeDefs, 
  resolvers,
});

server.listen().then(({ url }) => {
  console.log(`🚀 server live @ ${url}`);
});

const ws = new WebsocketClient({key: API_KEY, secret: PRIVATE_KEY}, logger);

ws.subscribe(["klineV2.1.BTCUSD"]);

ws.on('open', function() {
    console.log('connection open');
});

ws.on('update', function(message) {
    const btcusdOpen = message.data[0].open;
    const btcusdClose = message.data[0].close;
    const btcusdHigh = message.data[0].high;
    const btcusdLow = message.data[0].low;
    const btcusdTime = message.data[0].timestamp;

    console.log(message);

    // define Schema
    var BTCUSDklineSchema = mongoose.Schema({
      time: Number,
      open: Number,
      high: Number,
      low: Number,
      close: Number,
    });
    // compile schema to model
    var Data = mongoose.model('Data', BTCUSDklineSchema, 'BTCUSDkline');

    // a document instance
    var data1 = new Data({ time:btcusdTime, open:btcusdOpen, high:btcusdHigh, low:btcusdLow, close: btcusdClose });

    // save model to database
    data1.save(function (data) {
      console.log("just saved to BTCUSDkline collection!");
    });

});

ws.on('response', function(response) {
    console.log('response', response);
});

ws.on('close', function() {
    console.log('connection closed');
}); 
ws.on('error', function(err) {
    console.error('ERR', err);
}); 

which works the first time but then throws the following error the second time around:

throw new _mongoose.Error.OverwriteModelError(name);
      ^

OverwriteModelError: Cannot overwrite `Data` model once compiled.

Solution

  • You should put the Schemas outside the function, maybe after calling mongoose itself, so they will be ~ globally ~ available from mongoose once they're set and compiled.

    Every time someone sends something through ws, the function tries to define the Data Schema, which has been already defined and compiled by mongoose before.

    Instead of defining the Schame inside a function, like this:

    ws.on('update', function(message) {
        // ... message definition
    
        // define Schema
        var BTCUSDklineSchema = mongoose.Schema({
          time: Number,
          open: Number,
          high: Number,
          low: Number,
          close: Number,
        });
        // compile schema to model
        var Data = mongoose.model('Data', BTCUSDklineSchema, 'BTCUSDkline');
    
        // a document instance
        var data1 = new Data({ time:btcusdTime, open:btcusdOpen, high:btcusdHigh, low:btcusdLow, close: btcusdClose });
    
        // save model to database
        data1.save(function (data) {
          console.log("just saved to BTCUSDkline collection!");
        });
    });
    

    You should set the Schema outside any function, like this:

    // define Schema
    const BTCUSDklineSchema = mongoose.Schema({
      time: Number,
      open: Number,
      high: Number,
      low: Number,
      close: Number,
    });
    
    // compile schema to model
    const Data = mongoose.model('Data', BTCUSDklineSchema, 'BTCUSDkline');
    
    ws.on('update', function(message) {
        // ... message definition
    
        // a document instance
        var data1 = new Data({ time:btcusdTime, open:btcusdOpen, high:btcusdHigh, low:btcusdLow, close: btcusdClose });
    
        // save model to database
        data1.save(function (data) {
          console.log("just saved to BTCUSDkline collection!");
        });
    });