1

In the MEAN app I'm currently building, the client-side makes a $http POST request to my API with a JSON array of soundcloud track data specific to that user. What I now want to achieve is for those tracks to be saved to my app database under a 'tracks' table. That way I'm then able to load tracks for that user from the database and also have the ability to create unique client URLs (/tracks/:track)

Some example data:

{
    artist: "Nicole Moudaber"
    artwork: "https://i1.sndcdn.com/artworks-000087731284-gevxfm-large.jpg?e76cf77"
    source: "soundcloud"
    stream: "https://api.soundcloud.com/tracks/162626499/stream.mp3?client_id=7d7e31b7e9ae5dc73586fcd143574550"
    title: "In The MOOD - Episode 14"
}

This data is then passed to the API like so:

app.post('/tracks/add/new', function (req, res) {
     var newTrack;
     for (var i = 0; i < req.body.length; i++) {

        newTrack = new tracksTable({
            for_user: req.user._id,
            title: req.body[i].title,
            artist: req.body[i].artist,
            artwork: req.body[i].artwork,
            source: req.body[i].source,
            stream: req.body[i].stream
        });

        tracksTable.find({'for_user': req.user._id, stream: req.body[i].stream}, function (err, trackTableData) {

            if (err)
                console.log('MongoDB Error: ' + err);

            // stuck here - read below

            });    

        }
    });

The point at which I'm stuck, as marked above is this: I need to check if that track already exists in the database for that user, if it doesn't then save it. Then, once the loop has finished and all tracks have either been saved or ignored, a 200 response needs to be sent back to my client.

I've tried several methods so far and nothing seems to work, I've really hit a wall and so help/advice on this would be greatly appreciated.

ma08
  • 3,654
  • 3
  • 23
  • 36
leaksterrr
  • 3,800
  • 7
  • 34
  • 65
  • 1
    Why not create a compound index `db.collection.createIndex( {for_user:1, title:1}, {unique, true} )`? – Bart Aug 12 '14 at 20:11
  • What will that achieve? – leaksterrr Aug 12 '14 at 20:15
  • It will enable you to only store unique combinations of those indexes. You get an error in case of duplicates – Bart Aug 13 '14 at 03:56
  • @Bart I'm not too bothered about there being duplicates at this time. The app relies on the users soundcloud feed which is constantly changing but I'd like to keep a local copy saved in my db. I need to check that the item from the soundcloud JSON isn't already in the database before the app decides whether to save it to the database or not. – leaksterrr Aug 13 '14 at 20:49

3 Answers3

0

Create a compound index and make it unique. Using the index mentioned above will ensure that there are no documents which have the same for_user and stream.

trackSchema.ensureIndex( {for_user:1, stream:1}, {unique, true} )

Now use the mongoDB batch operation to insert multiple documents.

//docs is the array of tracks you are going to insert.

trackTable.collection.insert(docs, options, function(err,savedDocs){
 //savedDocs is the array of docs saved.
 //By checking savedDocs you can see how many tracks were actually inserted
})

Make sure to validate your objects as by using .collection we are bypassing mongoose.

ma08
  • 3,654
  • 3
  • 23
  • 36
  • I'm not bothered about duplicates being saved, the issue is that I want to check if the track from soundcloud JSON feed is already in the database – leaksterrr Aug 13 '14 at 20:48
0

Make a unique _id based on user and track. In mongo you can pass in the _id that you want to use.

Example {_id : "NicoleMoudaber InTheMOODEpisode14", artist: "Nicole Moudaber" artwork: "https://i1.sndcdn.com/artworks-000087731284-gevxfm-large.jpg?e76cf77" source: "soundcloud" stream: "https://api.soundcloud.com/tracks/162626499/stream.mp3? client_id=7d7e31b7e9ae5dc73586fcd143574550" title: "In The MOOD - Episode 14"}

_id must be unique and won't let you insert another document with the same _id. You could also use this to find the record later db.collection.find({_id : NicoleMoudaber InTheMOODEpisode14})

or you could find all tracks for db.collection.find({_id : /^NicoleMoudaber/}) and it will still use the index.

There is another method to this that I can explain if you dont' like this one.

Both options will work in a sharded environment as well as a single replica set. "Unique" indexes do not work in a sharded environment.

Sam
  • 21
  • 3
0

Soundcloud API provides a track id, just use it. then before inserting datas you make a

tracks.find({id_soundcloud : 25645456}).exec(function(err,track){ 
    if(track.length){ console.log("do nothing")}else {//insert}
 });
Su4p
  • 865
  • 10
  • 24