Azure documentdb stored procedure returning partial result - javascript

Currently I have got given stored procedure
function getData() {
var context = getContext();
var collection = context.getCollection();
var output = collection.map(function (doc) {
return {
id: doc.id,
name: doc.name,
status: doc.status,
description: doc.description,
owner: doc.owner
}
})
return JSON.stringify(output)
}
Issue here is that it only returs 7 documents (matching what you get when you not get 'load' action on azure panel) and is skipping rest of the collection.
I believe that it can be fixed with using SQL query syntaxt but I would like to know how can I query all documents in the collection without using it.

Try adding a FeedCallback like shown here and make the signature of the callback be function(error, resources, options). Look for errors. Also inspect the options parameter for a continuation. If that fails to give you enough information to fix the problem, then you might want to consider a more traditional query and transformation approach not using collection.map().

Related

Stored procedure azure Cosmos DB returns empty collection

I tried to create a stored procedure using the sample sp creation code from Azure docs, but i couldn't fetch the collection details. It always returns null.
Stored Procedure
// SAMPLE STORED PROCEDURE
function sample(prefix) {
var collection = getContext().getCollection();
console.log(JSON.stringify(collection));
// Query documents and take 1st item.
var isAccepted = collection.queryDocuments(
collection.getSelfLink(),
'SELECT * FROM root r',
function (err, feed, options) {
if (err) throw err;
// Check the feed and if empty, set the body to 'no docs found',
// else take 1st element from feed
if (!feed || !feed.length) {
var response = getContext().getResponse();
response.setBody('no docs found');
}
else {
var response = getContext().getResponse();
var body = { prefix: prefix, feed: feed[0] };
response.setBody(JSON.stringify(body));
}
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
The console shows only this.
the results shows no doc found because of not getting collection.I have passed the partition key at time of execution via explorer.
I had a similar issue. I think the Azure portal doesn't execute stored procedures properly when the partition key is not a string.
In my case I had a partitionKey that is a number. When I executed the stored procedure via the portal I always got an empty resultSet, even though I had documents in my database. When I changed the structure a little, and made my partitionKey a string, the stored procedure worked fine.
Did you create the ToDoList Database with the Items Collection? Yo can do this from the Quick start blade in the Azure portal.
And then create an SP to run against that collection. There is no partition key required, so no additional params are required (leave blank).
The Collection is created without any documents. You may choose to add documents via the Query Explorer blade or via the sample ToDoList App that is available via the Quick start blade.
You are debugging in a wrong way.
It is perfectly fine to see "{\"spatial\":{}}" in your console log, even if the collection has items. Why? well because that is a property of that object.
So regarding what you said:
the results shows no doc found because of not getting collection
is false. I have the same console log text, but I have items in my collection.
I have 2 scenarios for why your stored procedure return no items:
I had the same issue trying on azure portal UI(in browser) and for my surprise I had to insert an item without the KEY in order that my stored procedure to see it.
On code you specify the partition as a string ie. new PartitionKey("/UserId") instead of your object ie. new PartitionKey(stock.UserId)

Parse - limit result of a Query in Cloud Code

Hello is this code in the comment possible with Parse Cloud Code?
Parse.Cloud.beforeFind('Note', function(req) {
var query = req.query;
var user = req.user;
// if a given 'Note' visibility is set to 'Unlisted'
// return only the Notes with 'user' field that the calling _User
});
The documentation only shows how to filter fields that are returned but not exactly remove items from the query result in the Cloud Code.
This can be done through ACL, I know, but the caveat is that if the request is a retrieve function and not query the Note should still return.
Assuming you've saved the user as an object relationship (not a string id). Just add the qualification you need, such as:
query.equalTo("your_user_pointer_col_on_Note", user)

Search for artist id by name

I am delving into spotify and javascript is not my main programming language so I managed to get some snippets together from a code that uses ajax (which I would rather not use) but still it returns nothing so I am wondering if some more experienced people out there could help me get started with a template to call the api.
My goal for this test is to search an artist name and get the first result (I expect many names will return multiple artists)
Most of what is in the documentation is curl and I didn't find the demos very helpful.
What I have so far is something like this:
function getArtistName (artistName) {
var artistID;
var searchArtists = function (query) {
$.ajax({
url: 'https://api.spotify.com/v1/search',
data: {
q: query,
type: 'artist',
'accessToken': 'BQBvW70gHJ20Flc8cHErqg8s72bfTePbssblED-gpEuHFr_Yezesbthok8qaKBmjzo2WjWo9J7ZcTpSwvV8MZ_cW_E7UkrG_HF2R6gFQcqfdupgYGmoYsdRdt1q3tq2NU3pPgauuzmFLkUpdAuNp3shdVXJz2SzvnA',
'query': artistName,
limit: '1.'
},
success: function (response) {
//resultsPlaceholder.innerHTML = template(response);
}
});
};
console.log(searchArtists);
return artistID;
}
Some points of confusion:
The key seems to expire. I have a client ID on my profile but I am not sure where I can generate this token other than the "try it out" demo on the site.
What does this actually return, an ID or a JSON?
Here is a demo app that searches tracks using Node.js, or server-side Javascript: https://spotify-quicksearch.glitch.me/
If you click the "Remix this on Glitch" link on the page, you can see and edit the source.
The call to the API is made in server.js. First, we set the client ID and client secret, which are from the dashboard, as you've noted. In this example, we use those to get an access token using the Client Credentials Flow. You can read about all the authentication flows here: https://beta.developer.spotify.com/documentation/general/guides/authorization-guide/
This particular example uses an API wrapper called spotify-web-api-node, which just makes it easier to interact with the API through Javascript functions. To search for artists instead, just change searchTracks to searchArtists.
To answer your second question - all calls to the Spotify API return JSON. You can see the format of the full JSON response here: https://beta.developer.spotify.com/documentation/web-api/reference/search/search/. Roughly, it looks like this:
artists: {
items: [
{
id: <id>,
name: <name>,
...
}
...
]
}
To get the ID from the JSON, you need to parse the JSON object. You can see how I do this in the example in line 21 of client.js. You can modify that code to get just the ID of the first artist like this:
data.artists.items[0].id
Update: made an example that should be even more relevant:
https://spotify-search-artist.glitch.me/

Meteor: Best practice for modifying document data with user data

Thanks for looking at my question. It should be easy for anyone who has used Meteor in production, I am still at the learning stage.
So my meteor setup is I have a bunch of documents with ownedBy _id's reflecting which user owns each document (https://github.com/rgstephens/base/tree/extendDoc is the full github, note that it is the extendDoc branch and not the master branch).
I now want to modify my API such that I can display the real name of each owner of the document. On the server side I can access this with Meteor.users.findOne({ownedBy}) but on the client side I have discovered that I cannot do this due to Meteor security protocols (a user doesnt have access to another user's data).
So I have two options:
somehow modify the result of what I am publishing to include the user's real name on the server side
somehow push the full user data to the clientside and do the mapping of the _id to the real names on the clientside
what is the best practice here? I have tried both and here are my results so far:
I have failed here. This is very 'Node' thinking I know. I can access user data on clientside but Meteor insists that my publications must return cursors and not JSON objects. How do I transform JSON objects into cursors or otherwise circumvent this publish restriction? Google is strangely silent on this topic.
Meteor.publish('documents.listAll', function docPub() {
let documents = Documents.find({}).fetch();
documents = documents.map((x) => {
const userobject = Meteor.users.findOne({ _id: x.ownedBy });
const x2 = x;
if (userobject) {
x2.userobject = userobject.profile;
}
return x2;
});
return documents; //this causes error due to not being a cursor
}
I have succeeded here but I suspect at the cost of a massive security hole. I simply modified my publish to be an array of cursors, as below:
Meteor.publish('documents.listAll', function docPub() {
return [Documents.find({}),
Meteor.users.find({}),
];
});
I would really like to do 1 because I sense there is a big security hole in 2, but please advise on how I should do it? thanks very much.
yes, you are right to not want to publish full user objects to the client. but you can certainly publish a subset of the full user object, using the "fields" on the options, which is the 2nd argument of find(). on my project, i created a "public profile" area on each user; that makes it easy to know what things about a user we can publish to other users.
there are several ways to approach getting this data to the client. you've already found one: returning multiple cursors from a publish.
in the example below, i'm returning all the documents, and a subset of all the user object who own those documents. this example assumes that the user's name, and whatever other info you decide is "public," is in a field called publicInfo that's part of the Meteor.user object:
Meteor.publish('documents.listAll', function() {
let documentCursor = Documents.find({});
let ownerIds = documentCursor.map(function(d) {
return d.ownedBy;
});
let uniqueOwnerIds = _.uniq(ownerIds);
let profileCursor = Meteor.users.find(
{
_id: {$in: uniqueOwnerIds}
},
{
fields: {publicInfo: 1}
});
return [documentCursor, profileCursor];
});
In the MeteorChef slack channel, #distalx responded thusly:
Hi, you are using fetch and fetch return all matching documents as an Array.
I think if you just use find - w/o fetch it will do it.
Meteor.publish('documents.listAll', function docPub() {
let cursor = Documents.find({});
let DocsWithUserObject = cursor.filter((doc) => {
const userobject = Meteor.users.findOne({ _id: doc.ownedBy });
if (userobject) {
doc.userobject = userobject.profile;
return doc
}
});
return DocsWithUserObject;
}
I am going to try this.

node.js how to handle change of objects and variables in callbacks

I have just started a large project with node.js and I have stumbled upon some callback nightmare issues. I have done some node.js development before, but only small stuff based on tutorials.
I have a user model and a owner model, who is the owner for that user...basically the part I am building in node.js will be a REST service so I need to send a json containing a user and it's owner name. My problem is trying to get the owner name like I would do it in ruby or php and setting it as a property..but it doesn't work.
How do people handle this kind of logic in node.js where you need to change objects in callback functions? Also I do not want it to affect performance.
I am using mysql as the database because this was a requirement. So the code is this:
//find all
req.models.users.find({
'id' : req.query.id
}, function(err, users) {
if (err) console.log(err); //do something better here
else {
var json = [];
users.forEach(function(user) {
user.getOwner(function(err, owner) {
user.accountOwner = owner.name;
json.push(user;
});
});
res.type('application/json');
res.send(json);
}
});
I want to send something like this:
[{
'id': user.id,
'username": user.username,
'email': user.email,
'owner': user.owner.name'
},
{...}]
The problem is you are not understanding the control flow of node code. It doesn't go line by line top to bottom in chronological order. So your issue is your res.send(json) happens BEFORE (in time) your user.getOwner callback executes, so you send your empty json, then you stuff things into the json array after it's already been sent. You need to use something like async.each to do your joins, wait for all of the user`s owners to be populated, and then send the response. Or you could actually let the database join the data by writing a SQL join instead of doing N+1 queries against your database.

Categories