mysql – Synchronize Local Database from remote server on IONIC

Question:

Personal how-to to update a database in a mobile application every time the remote database is updated.

For example I have an application in ionic, and to get faster I use the database of contact lookup locally however this data is updated remotely, this way I need to update the local database of the mobile application.

I have two forms of Local database, one is loading a JSON file:

$http.get('js/dados.json').then(function(response) {
 angular.forEach(response.data, function(items) {
  $scope.total = items.length;
  for (i=0; i < $scope.limite; i++) {
    $scope.chats.push(items[i]);
  }
 });
}

In another example I load data from an SQLite:

$scope.select = function(lastname) {
    var query = "SELECT firstname, lastname FROM people WHERE lastname = ?";
    $cordovaSQLite.execute(db, query, [lastname]).then(function(res) {
        if(res.rows.length > 0) {
            console.log("SELECTED -> " + res.rows.item(0).firstname + " " + res.rows.item(0).lastname);
        } else {
            console.log("No results found");
        }
    }, function (err) {
        console.error(err);
    });
}

https://blog.nraboy.com/2014/11/use-sqlite-instead-local-storage-ionic-framework/

Anyone would have any solution for this.

Answer:

Old question, but I hope this answer will be useful for other googlers.

I'll give you an example of how to do it. (untested code!)

Create the factory below: it stores your contacts in memory, in the atuais variable which is only accessible through the getContatos() function

.factory('Contato',  function () {

   var atuais = { last: 0, contatos: {} };

   var ContatoFactory = {

        setContatos: function(novos) {   
            var processed = 0;
            if (isPresent(novos)) {
                if (atuais.last<novos.last) {
                    if (isPresent(novos.contatos)) {
                        atuais.last = novos.last;

                        for (var key in novos.contatos) {
                            if (!atuais.contatos[key]) atuais.contatos[key] = {};
                            angular.copy(novos.contatos[key],  atuais.contatos[key]);
                            processed++;
                        }
                    } else {
                        console.log('setContatos: falhou: novos.contatos = ' + novos.contatos);
                    }
                } else {
                    console.log('setContatos: falhou: atuais.last [' + atuais.last + '] >= novos.last [' + novos.last + ']');
                }
            } else {
                console.log('setContatos: nenhum contato novo para processar');
            }
            console.log('setContatos: ', processed, ' contatos processados');
        },
        getContatos: function() {
            console.log('getContatos: ' + angular.toJson(atuais) );
            return angular.copy(atuais);
        },
        clearContatos: function() {
            angular.copy({ last:0, contatos: {} }, atuais);
            console.log('clearContatos: ' + angular.toJson(atuais) );
        },
        persistirContatos: function() {
            //seu código aqui para salvar no SQLite ou LocalStorage
            //exemplo:
            localStorage.setItem('meusContatos', angular.toJson(atuais) );
        }
   };
   return ContatoFactory;
})

Somewhere in your code, you'll retrieve the backend contacts via AJAX (don't forget to inject your Factory in order to use it):

$http({
  method: 'GET',
  url: 'http://meuServidor.com/contatos?last=' + lastPosixUpdate
}).then(function successCallback(response) {
      Contato.setContato(response);  // response => { last: <POSIX_DATE>, contatos: { key1: {nome: 'abc', fone: '123' },  key2: {nome: 'xyz', fone: '456'}, ... }  }    
  }, function errorCallback(response) {
    console.log('Ajax falhou');
  });

Then you can retrieve your contacts on any controller in your App:

$scope.contatos = Contato.getContatos();

In the same way, you can persist your data when you see fit:

Contato.persistirContatos();

See that the backend sends a JSON like this:

{ last: <POSIX_DATE>, contatos: { key1: {nome: 'abc', fone: '123' },  key2: {nome: 'xyz', fone: '456'}, ... }  } 

where last must be a number representing the last change performed in the contact table. Thus, the response will only be processed if there are new or changed contacts.

Likewise, $http.get sends a querystring last=238274 to signal the backend as of when it wants contact updates.

You can implement such a last (which is good when the contact list is huge) or simply retrieve all contacts always.

auxiliary function:

//retorna true se o objeto existe e é não vazio
function isPresent(obj) {
    return obj && (Object.keys(obj).length!==0);
}
Scroll to Top