cosmosdb geospatial look up return blank - node.js

I am using cosmosDB to do a $geowithin lookup and when i run the query in the cosmosdb data explorer it works fine and returns the right set. When i run it in node js using the MongoClient I get back a empty set.
This is the query i ran in cosmosdb data explorer:
{CurrentLoc: {
$geoWithin: {
$centerSphere: [[-122.0312186,37.33233141], 0.0025232135647961246]
}
}}
That returned the correct list of documents
This is in my node app:
var toFind = {
CurrentLoc: {
$geoWithin: {
$centerSphere: [currentLoc, maxDistance]
}
}
}
var query = db.collection('User').find(toFind)
query.toArray(function (err, doc, queryResult) {
logger.debug ('result: ' + JSON.stringify(doc);
})
That returns a blank set and does not get the data back. Why would it be returning different things and also why is it blank?

You might need to break down the currentLoc variable into an array of two values, so the query is structured in the same manner as when executed through CosmosDB Data Explorer:
[-122.0312186,37.33233141] in
$centerSphere: [[-122.0312186,37.33233141], 0.0025232135647961246]
Hope it helps!

Related

query to mongoDB doesnt work when i use an array variable , but works when i explicitly write the array in the AND query (Nodejs)

can anyone explain as to why does this query to mongoDB works when i write the array explicitly like this in the AND operator
async function getAds(queryParams) {
return ad = await ads.Ad.find()
.and( { tags : { $all: ["karachi","lahore"] }}));
}
but doesnt work when i retrieve the array of tags from the query params and put directly in the AND operator?
like this
async function getAds(queryParams) {
return ad = await ads.Ad.find()
.and( { tags : { $all: queryParams.tags }}));
}
and yes i checked with ' and also ", and also i checked queryParams.tags, it is exactly equals to ["karachi","lahore"]

I want to insert documents using upsert in mongoose

I am fetching data from an external api and I want to insert multiple records if they are not already there . I am creating an array of objects like this :
data=[
{
match_id: 212167781,
player1Id: 129753806,
player2Id: 129753811,
player1Details: '5f070c8f79f62c00042b0cd8',
player2Details: '5f3267fe6a0f891b3604b999'
},
{
match_id: 212167782,
player1Id: 129753799,
player2Id: null,
player1Details: '5f070ade79f62c00042b0cd6'
}
]
Now for instance if the second record is not already present then I want it to be inserted and I have tried upsert but nothing happens . Please help .
You should be able to do this using a simple loop and Model.findOneAndUpdate in combination with the upsert option:
async function upsertMany(data) {
for(const entry of data) {
await YourModel.findOneAndUpdate(entry, entry, { upsert: true });
}
}
// call this with your data-array
await upsertMany(data);

Google Datastore NodeJS combine (union) multiple sets of keys only results

I am working with NodeJS on Google App Engine with the Datastore database.
Note that this question is an extension of (not a duplicate) my original post.
Due to the fact that Datastore does not have support the OR operator, I need to run multiple queries and combine the results.
Here is my approach (based on the selected answer from my original post):
Use Keys-only queries in the 1st stage
Perform the combination of the keys obtained into a single list (including deduplication)
Obtaining the entities simply by key lookup
I have achieved #1 by running two separate queries with the async parallel module. I need help with step 2.
Question: How to combine (union) two lists of entity keys into a single list (including de-duplication) efficiently?
The code I have below successfully performs both the queries and returns two objects getEntities.requesterEntities and getEntities.dataownerEntities.
//Requirement: Get entities for Transfer Requests that match either the Requester OR the Dataowner
async.parallel({
requesterEntities: function(callback) {
getEntitiesByUsername('TransferRequest', 'requester_username', loggedin_username, (treqs_by_requester) => {
//Callback pass in response as parameter
callback(null, treqs_by_requester)
});
},
dataownerEntities: function(callback) {
getEntitiesByUsername('TransferRequest', 'dataowner_username', loggedin_username, (treqs_by_dataowner) => {
//Callback pass in response as parameter
callback(null, treqs_by_dataowner)
});
}
}, function(err, getEntities) {
console.log(getEntities.requesterEntities);
console.log(getEntities.dataownerEntities);
//***HOW TO COMBINE (UNION) BOTH OBJECTS CONTAINING DATASTORE KEYS?***//
});
function getEntitiesByUsername(kind, property_type, loggedin_username, getEntitiesCallback) {
//Create datastore query
const treq_history = datastore.createQuery(kind);
//Set query conditions
treq_history.filter(property_type, loggedin_username);
treq_history.select('__key__');
//Run datastore query
datastore.runQuery(treq_history, function(err, entities) {
if(err) {
console.log('Transfer Request History JSON unable to return data results for Transfer Request. Error message: ', err);
} else {
getEntitiesCallback(entities);
}
});
}
I was able to combine the two separate sets of entity keys by iterating over the arrays and comparing the ID values for each entity key and creating a new array with the unique keys.
Note: The complete solution is posted as an answer to my original post.
//Union of two arrays of objects entity keys
function unionEntityKeys(arr1, arr2) {
var arr3 = [];
for(var i in arr1) {
var shared = false;
for (var j in arr2)
if (arr2[j][datastore.KEY]['id'] == arr1[i][datastore.KEY]['id']) {
shared = true;
break;
}
if(!shared) {
arr3.push(arr1[i])
}
}
arr3 = arr3.concat(arr2);
return arr3;
}

Convert a string parameter into float in Cloudant query

I need to do a query in an Cloudant DataBase where you compare a number with decimals that is defined as a string with another number sent from the server. The problem is that a comparison of strings is made and I need it to be a numerical comparison. There is there any way to perform this search by converting the database parameter to float while doing the query? O there are another way to do this query?
This is the query in the server, value.precio is sent from the client as a string.
value.precio = value.precio.split("-");
var precio_init = value.precio[0];
var precio_final = value.precio[1];
value.precio = {
"$gte":precio_init,
"$lte":precio_final
};
And in my database this is the parameter I want to search is:
"precio": "13.39"
Thanks
I don't think you will be able to do this with Cloudant Query, but you could try Cloudant Search. Create a new search index similar to the following:
Design Doc: myDesignDoc
Index Name: byPrecio
Index:
function (doc) {
if (doc.precio) {
index("precio", parseFloat(doc.precio));
}
}
Then you can uses ranges to search. For example:
precio:[13 TO 14]
Full search on Cloudant would look like this:
https://xxx.cloudant.com/YOUR_DB/_design/myDesignDoc/_search/byPrecio?q=precio:[13%20TO%2014]&include_docs=true
Sample response:
{
"total_rows":1,
"bookmark":"g2wAAAAxxx",
"rows":[
{
"id":"74fa6ff1b6dbca8c10d677832f6a3de2",
"order":[
1.0,
0
],
"fields":{
},
"doc":{
"_id":"74fa6ff1b6dbca8c10d677832f6a3de2",
"_rev":"2-17c984e51102b719fe9f80fc5d5bc78e",
"precio":"13.39",
"otherField":"otherValue"
}
}
]
}
More info on Cloudant Search here

Cloudant Query 2.0 unexpected behavior

I create an index using the below function:
function (doc) {
if(doc.type === 'Property') {
if(doc.Beds_Max) {
try {
index("Beds_Max", parseInt(doc.Beds_Max));
}
catch(err) {
//ooopss
}
}
if(doc.YearBuilt) {
try {
index("YearBuilt", parseInt(doc.YearBuilt));
}
catch(err) {
//ooopss
}
}
}
}
using the cloudant Design Documents -> New Search Index and after the index is built I can issue queries like
"YearBuilt": [2010 TO Infinity]
But if I try to query the same index using Cloudant query I see weird behavior. If I go to Cloudant Dashboard -> Query and pass something like
{"limit": 5,
"selector": {
"_id": {
"$gt": null
},
"Beds_Max": {"$gte": 7}
},
fields: ["_id"]}
I see huge spike in data transmission, it keeps on receiving huge amounts of data even for the most unusual queries which are only supposed to return no more than 1 or 2 results and then hangs my computer so that most probably is not right. When I use Pouchdb-find npm module which has support for Cloudant 2.0 Query and issue the same selector as above I see inconsistent behavior, e.g. sometimes it returns 0 rows and sometimes it gives a ETIMEOUTERROR. If I change the index and exclude parseInt I can query using the same Pouchdb-find and even Cloudant Dashboard-> Query and get the results but in that case I lose the ability to use inequality operators which is a no go for me.
I'm open to work-arounds and even altogether different features to achieve the desired result.

Resources