Storing data in MongoDB upon the emission of a Socket.io event

In my project, I am using a MEAN stack and Socket.io to retrieve images from the real-time Instagram API. The current setup is functioning well, but now I want to store image data in a MongoDB database to maintain a record of images based on locations, rather than just displaying the most recent photos.

Below is the code snippets that are currently working:

Node server-side code for handling new photo updates from Instagram API and emitting an event to Angular controller:

// Code to handle new posts from Instagram
app.post('/callback', function(req, res) {
    var data = req.body;

    // Extract object_id as geo_id from each subscription and send it to the client side
    data.forEach(function(data) {
        var geo_id = data.object_id;
        sendUpdate(geo_id);
    });
    res.end();
});

// Emit the URL with the geo_id to the client side for AJAX call
function sendUpdate(geo_id) {
    io.sockets.emit('newImage', { geo_id: geo_id });
}

Angular controller code for receiving 'newImage' event:

socket.on('newImage', function(geo_id) {
    // Call Instagram API with geo_id parameter
    Instagram.get(geo_id).success(function(response) {
        instagramSuccess(response.geo_id, response);
    });

    // Callback function for Instagram API
    var instagramSuccess = function(scope,res) {
        if (res.meta.code !== 200) {
            scope.error = res.meta.error_type + ' | ' + res.meta.error_message;
            return;
        }
        if (res.data.length > 0) {
            $scope.items = res.data;
        } else {
            scope.error = "This location has returned no results";
        }
    };
});

Angular factory for making calls to Instagram API:

angular.module('InstaFactory', []).factory('Instagram', function($http) {
    var base = "https://api.instagram.com/v1";
    var client_id = 'MY-CLIENT-ID';

    return {
        'get': function(geo_id) {
            var request = '/geographies/' + geo_id.geo_id + '/media/recent?client_id=' + client_id;
            var url = base + request;
            var config = {
                'params': {
                    'callback': 'JSON_CALLBACK'
                }
            };
            return $http.jsonp(url, config);
        }
    };

I also have an Angular Controller that retrieves details of each location from my Stadia MongoDB model. The model includes an empty 'photos' array where I intend to add photo details (URL, username, user profile URL, etc.) every time they are received from Instagram:

angular.module('StadiaFactory', []).factory('Stadia', function($http) {
    var base = "http://localhost:6060/api/stadia/";

    return {
        'get': function(id) {
            var request = id;
            var url = base + request;
            var config = {
                'params': {
                    'callback': 'JSON_CALLBACK'
                }
            };
            return $http.jsonp(url, config);
        }
    };

});

I am unsure about where to initiate the PUT request to my Stadia API and whether the Node route for my Stadia API is appropriate. Note: My GET route is functioning correctly, but I am facing challenges with the PUT request:

// Add photos to stadium's photos array
app.put('/api/stadia/:stadium_id', function(req, res) {

    // Utilize mongoose to retrieve and update stadium
    Stadium.findByIdAndUpdate(req.params.stadium_id,
        {$push: {"photos": {img: ?, link: ?, username: ?, profile_picture: ?}}},
        {safe: true, upsert: true},
        function(err, stadium) {

        // If there is an error, send the error message
        if (err)
            res.send(err)

        res.jsonp(stadium); // Return updated stadium in JSON format
    });
});

Answer №1

There are several issues with the current structure that need to be addressed.

One problem is that every time the callback route is triggered, it fetches all the latest photos for your geography, even if there are multiple objects present. This means unnecessary data retrieval and processing, especially when handling new objects. Additionally, there may be duplication issues if clients attempt to obtain object data from the server and transmit it via PUT, leading to increased traffic and potential API limit concerns.


A more efficient approach would be to retrieve specific information directly on the server side within the callback function using the request module.

Focusing only on fetching pictures, you can filter out other unwanted data like users, tags, or videos. By listening specifically for image objects, you can optimize the data retrieval process.

An implementation example could look like this:

var request = require('request');
var CLIENT_ID = 'yourId';

function newImage(data) {
  io.sockets.emit('newImage', data);
}

app.post('/callback', function (req, res) {

  //iterate through new objects
  req.body.forEach(function (data) {

    if (data.type !== 'image') { return ; }

    //consider using id property instead of object_id
    request('https://api.instagram.com/v1/media/' + data.object_id + '?access_token=' + CLIENT_ID,
      function (error, response, body) {
        if (error) { return ; }
        
        var image = JSON.parse(body);

        //Store the new object in the DB (replace STADIUM_ID)
        Stadium.findByIdAndUpdate(STADIUM_ID, { $push: {'photos':
          { img: image.images.standard_resolution.url,
            link: image.link,
            username: image.user.username,
            profile_picture: image.user.profile_picture
          }}},
          { safe: true, upsert: true });

        //Send a socket message to the client with the new image
        newImage({
          id: image.id,
          img: image.images.standard_resolution.url,
          link: image.link,
          username: image.user.username,
          profile: image.user.profile_picture
        });
      }
  });

  res.end();

});

In the client-side logic, you simply need to handle the received images in the newImage socket event within the $scope.items.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to declare a global TypeScript variable in a definition file to make it accessible for import?

My issue revolves around an external JS library that contains a global parameter: function Thing() { ... } ... var thing = new Thing(); I have a TypeScript definition file named thing.d.ts with the following content: declare var thing: ThingStatic; ex ...

Save the data in Redux and access it back

I am currently using material-ui-dropzone to upload an array of files and store them in redux However, when I try to retrieve the file from the redux state, it is not recognized as type "File" and appears differently in devtools https://i.stack.imgur.com ...

Tips on accessing the value of a dynamic field in an ASP ModalPopup

I am having trouble with my modalpopup extender. When the user clicks an 'Add' button, a dynamic textbox is created within the popup. However, I am struggling to get a reference to this textbox in the codebehind. Adding a 'textchanged' ...

Encountering issues with the setValue function in Nightwatch

Currently, I am in the process of setting up a new Nightwatch project to automate a basic Google search page. The assertion for searchbox present on page is successful, but I am facing difficulties performing any mouse or keyboard actions on the elements ( ...

Is there a way to refresh a different webpage within the current session?

In the world of Asp.Net 4, there is a form waiting to be filled with numeric data by the customer. However, this task can sometimes prove tricky as customers may struggle to calculate and input the total figure for each of the four fields. An innovative s ...

What is the best way to incorporate an URL with AJAX in Yii framework?

Check Out This Page <script type="text/javascript"> $("#project").change(function(){ var data1=$("#project").val(); $.ajax({ type: "POST", url: "<?php echo Yii::app()->createUrl('ajaxfunc&a ...

Expanding Lists in Bootstrap 3: A Step-by-Step Guide

I have been experimenting with Bootstrap's Example accordion code, which can be accessed via this link: http://jsfiddle.net/qba2xgh6/18/ <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true"> <div class="panel ...

Ways to dynamically insert a new row into a table based on user input in a Postman-like reactive table

Is there a way to dynamically insert a row when a single character is entered into an input field in the header tab, similar to how Postman functions? 1) If a user types any single character in the td of the first row, then a new row should be added below ...

Array Filtering with Redux

I have come across similar queries, but I am still unable to find a solution. While typing in the search box, the items on the screen get filtered accordingly. However, when I delete a character from the search box, it does not show the previous items. For ...

Changing Background Color on Div Click

After spending a considerable amount of time on this, I find myself getting confused and stuck. It seems like I might be overlooking something crucial. Essentially, my code is designed to have the default div background (gamebg), and upon clicking one of t ...

What could be the reason my Angular interceptor isn't minified correctly?

I have come across this interceptor in my Angular project: angular.module('dwExceptionHandler', []) .factory('ExceptionInterceptor', ['$q', function ($q) { return function (promise) { return promise.th ...

What's the ideal file structure for Codeigniter paired with Angularjs?

Recently, I embarked on a project using Codeigniter and AngularJS for an app. However, I encountered some issues when attempting to use font-awesome offline. After investigating the problem, I concluded that it may be related to the file folder structure ...

Tips for ensuring a div stays centered while resizing the window

When I resize the window, the div tab on the right side of the screen moves to the bottom right. How can I make it stay in the middle regardless of screen size? I've tried using margin-left:auto and margin-right:auto but it didn't work. Changing ...

Retrieve the unique identifier of the dynamically created button

I have been struggling to retrieve the ID of a dynamically generated button. I attempted to access the specific button ID and utilize it for beforeSend:function(id). However, my efforts were not fruitful. <?php session_start(); require_once "../aut ...

The element is being offset by SVG animation that incorporates transform properties

I'm working on creating a halo effect by rotating an SVG circular element using the transform rotate function. I've been using getBox to find the center point of the element, but when the rotation occurs, the overall image is getting misaligned w ...

Get the file using jQuery ajax post request

Currently, I am attempting to export the data from my web page and download it as an Excel file. However, despite receiving a successful response, the download does not initiate. $.ajax({ type: "POST", url: _url, contentType: 'multi ...

Unresolved dependencies causing a rollup error

When I try to use import file from 'file.json' in a Vue component and run npm run build to bundle it with Rollup, I encounter an issue. An error is thrown during the process, preventing the file from being bundled as expected. https://i.sstatic ...

Sending JSON data containing an IFormFile and a string as parameters to C#

Software Versions: ASP.NET and Web Tools - 17.10.341.11210 C# Tools - 4.10.0-3.24312.19+ JQuery - 3.3.1.js JS - 2.8.3.js Currently, I am attempting to pass an IFormFile and a string from a JSON file select and a string input. After thorough testing, I ha ...

choosing a date from the UICalendar

Recently, I've started exploring Angular and I'm trying to incorporate a calendar feature using ui-calendar. So far, I've managed to display a basic calendar with some events on it. Now, my goal is to allow users to click on a specific day ...

The search functionality for the MongoDB module is not functioning properly within my Next.js application

Working on my nextjs application, I have encountered an issue with using the mongodb node module to find all documents in one of my collections. Despite successful usage of .findOne and .updateOne for other pages like login and password reset, when I use . ...