CloudantDB & NodeJS: Query data with specific id - angularjs

I just created a NodeJS cloudantDB web starter on bluemix. Then, I have a API get data from cloudantDB and get successfull but it returns all data. Please see js file:
js file:
app.get('/api/provider', function(request, response) {
console.log("Get method invoked.. ")
db = cloudant.use(dbCredentials.dbProvider);
var docList = [];
var i = 0;
db.list(function(err, body) {
if (!err) {
var len = body.rows.length;
console.log('total # of docs -> '+len);
if(len == 0) {
// error
} else {
body.rows.forEach(function(document) {
db.get(document.id, { revs_info: true }, function(err, doc) {
if (!err) {
if(doc['_attachments']) {
// todo
} else {
var responseData = createResponseDataProvider(
doc._id,
doc.provider_type,
doc.name,
doc.phone,
doc.mobile,
doc.email,
doc.logo,
doc.address
);
}
docList.push(responseData);
i++;
if(i >= len) {
response.write(JSON.stringify(docList));
console.log('ending response...');
response.end();
}
} else {
console.log(err);
}
});
});
}
} else {
console.log(err);
}
});
If I want to add parameter to API to get specific data from DB , Do we need create search index or query on cloudant, afer that call API the same : app.get('/api/provider/:id'). Please help me review and sharing. Thanks

you could get the document by id/name:
db.get(docID, function(err, data) {
// do something
});
references:
https://github.com/apache/couchdb-nano#document-functions
https://github.com/cloudant/nodejs-cloudant#api-reference

You can use a search function of Cloudant.
You need to create search index. In search index you can manage what data you want to get.
Example: https://cloudant.com/for-developers/search/
Following this code after create search index.
...
var query = {q: "id:doc.id"};
db.search('design document name', 'index name', query, function(er, result) {
if (er) {
throw er;
}
console.log(result);
});

Related

How to get all subcollection documents with subcollection name as a date? [duplicate]

Say I have this minimal database stored in Cloud Firestore. How could I retrieve the names of subCollection1 and subCollection2?
rootCollection {
aDocument: {
someField: { value: 1 },
anotherField: { value: 2 }
subCollection1: ...,
subCollection2: ...,
}
}
I would expect to be able to just read the ids off of aDocument, but only the fields show up when I get() the document.
rootRef.doc('aDocument').get()
.then(doc =>
// only logs [ "someField", "anotherField" ], no collections
console.log( Object.keys(doc.data()) )
)
It is not currently supported to get a list of (sub)collections from Firestore in the client SDKs (Web, iOS, Android).
In server-side SDKs this functionality does exist. For example, in Node.js you'll be after the ListCollectionIds method:
var firestore = require('firestore.v1beta1');
var client = firestore.v1beta1({
// optional auth parameters.
});
// Iterate over all elements.
var formattedParent = client.anyPathPath("[PROJECT]", "[DATABASE]", "[DOCUMENT]", "[ANY_PATH]");
client.listCollectionIds({parent: formattedParent}).then(function(responses) {
var resources = responses[0];
for (var i = 0; i < resources.length; ++i) {
// doThingsWith(resources[i])
}
})
.catch(function(err) {
console.error(err);
});
It seems like they have added a method called getCollections() to Node.js:
firestore.doc(`/myCollection/myDocument`).getCollections().then(collections => {
for (let collection of collections) {
console.log(`Found collection with id: ${collection.id}`);
}
});
This example prints out all subcollections of the document at /myCollection/myDocument
Isn't this detailed in the documentation?
/**
* Delete a collection, in batches of batchSize. Note that this does
* not recursively delete subcollections of documents in the collection
*/
function deleteCollection(db, collectionRef, batchSize) {
var query = collectionRef.orderBy('__name__').limit(batchSize);
return new Promise(function(resolve, reject) {
deleteQueryBatch(db, query, batchSize, resolve, reject);
});
}
function deleteQueryBatch(db, query, batchSize, resolve, reject) {
query.get()
.then((snapshot) => {
// When there are no documents left, we are done
if (snapshot.size == 0) {
return 0;
}
// Delete documents in a batch
var batch = db.batch();
snapshot.docs.forEach(function(doc) {
batch.delete(doc.ref);
});
return batch.commit().then(function() {
return snapshot.size;
});
}).then(function(numDeleted) {
if (numDeleted <= batchSize) {
resolve();
return;
}
// Recurse on the next process tick, to avoid
// exploding the stack.
process.nextTick(function() {
deleteQueryBatch(db, query, batchSize, resolve, reject);
});
})
.catch(reject);
}
This answer is in the docs
Sadly the docs aren't clear what you import.
Based on the docs, my code ended up looking like this:
import admin, { firestore } from 'firebase-admin'
let collections: string[] = null
const adminRef: firestore.DocumentReference<any> = admin.firestore().doc(path)
const collectionRefs: firestore.CollectionReference[] = await adminRef.listCollections()
collections = collectionRefs.map((collectionRef: firestore.CollectionReference) => collectionRef.id)
This is of course Node.js server side code. As per the docs, this cannot be done on the client.

Pagination in Watson Assistant api

I am trying to paginate the result from the watson conversation api. But I am unable to do that.
I have tried creating a function where I pass the url of the next_page but it doesn't work.
function callWatson(url) {
let watson_url = 'https://gateway.watsonplatform.net/assistant/api';
if (!url) {
watson_url = `${watson_url}/v1/workspaces/[workspace_id]/logs?version=2018-09-20`;
} else {
watson_url = `${watson_url}/${url}`;
}
assistant = new watson.AssistantV1({
username: ************,
password: ************,
url: watson_url,
rejectUnauthorized: false,
version: '2018-09-20'
});
return assistant;
}
let input = [];
let pagination = [];
assistant.listAllLogs(param, function(err, response) {
if (err) {
console.error(err);
} else {
for (var i = 0; i < response.logs.length; i++) {
pagination.push(response.pagination);
input.push(response.logs[i]);
}
// logger.debug(input);
logger.debug(pagination);
}
});
Based on the docs you need to use "next_url" - The URL that will return the next page of results, if any.
https://cloud.ibm.com/apidocs/assistant#pagination
You need to pass the next_cursor field from the pagination object in the current response as the value for the cursor parameter in the subsequent request.

How to create array of objects from http.get

I have http.get and it's impossible for me to create array of objects. Can you help me ? I need to create loop on array of returned objects and i can't do this.
export class Link {
idStat: String;
idAccount: String;
}
links: Link [];
router.get('/linkGetAll', function(req, res, next) {
Link.find(function (err, products) {
if (err) return next(err);
res.json(products);
});
});
getAllLinks(){
return this.http.get('/main/linkGetAll');
}
this.api.getAllLinks().subscribe((data) => {
this.links = data;
})
for(let item in this.links)
{
DOESN'T WORK
}
getAllLinks(){
return this.http.get('/main/linkGetAll')
.pipe(map(res => {
// do something here
// res.forEach() or res.map()
return 'it';
})
);
}
Before going to
for(let item in this.links)
{
DOESN'T WORK
}
Ensure that this.links has data in it.(use async/await along with toPromise())
Please read this section about HTTP of the Angular tutorial and the Angular API.
The get method accepts a type:
get<T>(...): Observable<T>
so you could modify your implementation of getAllLinks:
getAllLinks(): Observable<Link[] {
return this.http.get<Link[]>('/main/linkGetAll');
}
Now you should should be able to iterate the response:
getAllLinks().subscribe(links => {
links.forEach(link => // do what you need);
}

How to clear an array in MongoDB

I have an emails object that contains an array in a mongodb database. However, when I try to use $set to make the array empty it doesn't work. How am I supposed to clear the array?
exports.clearEmails = function(req, res, next) {
var listId = req.params.id;
var errors = req.validationErrors();
if (errors) {
return res.status(400).send(errors);
}
EmailList.update({'_id': listId}, {$set: {'emails': []}}, function(err,results) {
if (err) {
return res.status(400).send(err);
} else {
return res.status(200).send(results);
}
});
}

Mongodb query doesn't work

In my image sharing application you can upload images and create albums. When you delete an image from the site it shall also be deleted in the albums (the ones that has got the image in it).
Below is the route for deleting an image, and what I really need help with is why the code for deleting the images (imageName and imageId) in the albums below doesn't work.
Thanks in advance!
The models:
var AlbumSchema = new Schema({
title : String,
imageName : [String],
imageId : [String]
});
modelObject.AlbumSchema = AlbumSchema;
modelObject.Album = mongoose.model('Album', AlbumSchema);
-
var BlogPostSchema = new Schema({
name : String,
size : Number,
type : String,
author : ObjectId,
title : String
});
modelObject.Comment = mongoose.model('Comment', CommentSchema);
modelObject.BlogPost = mongoose.model('BlogPost', BlogPostSchema);
The part that doesn't work in the code below is the following:
albums[i].imageName.remove(j);
albums[i].imageId.remove(j);
albums[i].save(function (err){
if (err) {
console.log(err);
// do something
}
});
Full code:
app.get('/blog/delete/:id', function(req, res){
model.BlogPost.findById(req.params.id, function (err, blog){
var theImage = blog.name;
var query = albumModel.Album.find( { imageName:theImage } )
query.exec(function (err, albums) {
if (!albums) {
blog.remove(function(err) {
console.log(err);
// do something
});
res.redirect('/blogs');
}
else {
for (var i = 0; i < albums.length; i++) {
for (var j = 0; j< albums[i].imageName.length; j++){
if (theImage == albums[i].imageName[j]){
albums[i].imageName.remove(j);
albums[i].imageId.remove(j);
albums[i].save(function (err){
if (err) {
console.log(err);
// do something
}
});
}
}
}
}
blog.remove(function(err) {
console.log(err);
// do something
});
res.redirect('/blogs');
});
});
});
JavaScript arrays don't have a remove method so I would expect your code may be crashing. You should be using code like albums[i].imageName.splice(j, 1); instead.

Resources