Parse GeoPoint aggregate query - aggregate

I want to use that in my cloudCode.
I'm on Parse server 4.2.
I would like to know if it's possible de create a Parse Query and to use agregate on field with geoNear or geoWithin ?
Something like that for example:
const userLat = 43.3;
const userLng = 5.3;
const slotQuery = new Parse.Query(Slot);
return await slotsQuery.aggregate([
{
$geoNear: {
near: [userLat, userLng],
distanceField: 'meetPointLocation',
maxDistance: 2,
}
}
]);
Thanks everyone for your help!

Related

Functions inside MongoDB query

I was wondering if was possible to utilize functions inside of MongoDB query by including a function inside of options block or something.
Suppose my database collection has a document:
{"year": "2320"}
And I have function to format this document's year-field:
const reformat = function(input){
return input.year.substring(2,4)+input.year.substring(0,2)
}
And I'll be calling a fetch function like this:
const test = {"year": "2023"}
fetchSomething(test, {}, reformat)
My fetch function looks like this:
async function fetchSomething(query, projection, options){
const dat = await mongoCli.db("testDB").collection("testCollection").findOne(query, projection, options);
return dat;
}
So, reformat-function should modify the database's document to match year-attribute of test-variable, not the other way around.
I'm not sure if MongoDB even supports it. Looking at the MongoDB documentation...
All you could do is like this:
const reformat = function(){
return {allowDiskUse: true}
}
mongoCli.db("testDB").collection("testCollection").findOne(query, projection, reformat());
The option is an input attribute of findOne, you cannot re-define it.
Or you can use $function in aggregation pipeline:
db.mongoCli.aggregate([
{
$set: {
year: {
$function: {
body: function (input) {
return input.year.substring(2, 4) + input.year.substring(0, 2)
},
args: ["$$ROOT"],
lang: "js"
}
}
}
}
])
Please be aware, executing JavaScript inside an aggregation expression may decrease performance. Only use the $function operator if the provided pipeline operators cannot fulfill your application's needs. $substrCP and $concat are also available as pipeline operator.
I now realize is that I can accomplish it with a cursor:
const reformat = function(input){
return input.year.substring(2,4)+input.year.substring(0,2)
}
async function fetchSomething(query, options){
const cursor = await mongoCli.db("testDB").collection("testCollection").find()
let doc;
while (await cursor.hasNext()) {
doc = await cursor.next();
if (options(doc) == query.year){ break; }
else { doc = null; }
}
cursor.close();
return doc;
}
const test = {"year": "2023"}
fetchSomething(test, reformat)
Though there might be a better way to do it.

How to query data from `PostgresSql`?

I use NestJj,PostgreSQL and Graphql for Back-End,
Flutter,graphql_flutter for Front End.
I have a collection store like this :
I want to get the following result:
[
{
type:'A',
details:[
{name:'Food1'}
]
},
{
type:'Expense',
details:[
{name:'gym'},
{name:'Dinner'}
]
},
{
type:'Revenue',
details:[
{name:'Revenue'}
]
}
]
For show on the device :
How can I query?
Could you help me?
I'm not sure if you'll be able to build that structure at the level of SQL.
What you can do is to extract the data from the table wit the structure as it is and then map it at the level of JS.
// here's an example with TypeORM
const data = await Collection.findBy({...});
const result = data.map(item => ({
type: item.type,
details: [{
name: item.name
}]
}));
P.S. I'm pretty sure that's not the answer you've expected but it will solve your issue.

How to map Elasticsearch match_phrase query in flutter

I am trying to add elasticsearch to my flutter app.
I am using elastic_client to deal with the connection
How can I map the following query in flutter format?
POST /books/_search
{
"query": {
"match_phrase": {
"name" : {
"query" : "Roberts book",
"slop": 50
}
}
}
}
There is very little info about elasticsearch and flutter.
Right now I have the following code to do the query with elastic_client. But as far as I understand this package did not have the match_phrase implemented. And I need to query match_phrase.
final searchResult = await client.search(
index: 'books',
type: '_doc',
query: elastic.Query.term('name', ['$searchQuery'.toLowerCase()]),
source: true);
I followed this tutorial if you want to know more.
Update
With the help of #Vlad and the creator of the elastic_client
It might be useful for someone, so the full solution is:
final transport = HttpTransport(url: 'http://myip:9200/');
final client = elastic.Client(transport);
final searchResult = await client.search(
index : 'books',
type: '_doc',
query: {
"match_phrase": {
"name" : {
"query" : '$searchQuery'.toLowerCase(),
"slop": 50,
},
},
});
By following the match implementation source code, it looks like that these methods are just wrappers to create JSON. So based on that, I can derive, that you could do the following:
final searchResult = await client.search(
index: 'books',
type: '_doc',
query: {
'match_phrase': {
'name': {
'query': '$searchQuery'.toLowerCase(),
'slop': 50
}
},
};
source: true);
Note, that I have no experience with Flutter, this is just my thinking based on the source code.
Alternatively, you could create your own method which creates JSON for Elasticsearch.

.count aggregate significantly slows execution time

I am refactoring some old code to hope to speed up and make information more secure. In order to do so I am trying to use the MongoDB aggregation framework to get all users near a specific location. Originally this was being solved by handling some spherical calculations on the front end but to do so it was sending lat, lng coordinates of each user back to the front end which is insecure and exposes location data of users un-necessarily.
My solution is use the aggregation framework and $geoNear to get the list of nearby users and then also populate a field with the distance in miles called distanceAway. Everything is working well until I try to set up pagination. The $count stage slows the execution of the route dramatically.
Below is my code:
module.exports = async function findUsersNearLocationAggregate(baseLocation, page = 1, limit = 20) {
// quick validation on location object passed
if(!lodash.get(baseLocation, 'geometry.location', undefined))
throw new Error('NO_LOCATION_SPECIFIED')
// Grab user location to use as location origin
const { lat, lng } = baseLocation.geometry.location
let query = {
$geoNear: {
near: { type: "Point", coordinates: [lng, lat] },
distanceField: "distanceAway",
spherical: true,
distanceMultiplier: CONVERT_METERS_TO_MILES
}
}
const users = await User.aggregate([
query,
{ $skip: ((page - 1) * limit) },
{ $limit: limit }
])
// const [{ count }] = await User.aggregate([
// query,
// { $count: 'count' }
// ])
return {
user: users,
// totalPages: Math.ceil(count / limit)
// currentPage: page
}
}
This function was meant to return the list of users (limit of 20 at a time) and show other data such as totalPages and currentPage to track the pagination on the front-end and make subsequent requests.
When I comment out the following line:
const [{ count }] = await User.aggregate([
query,
{ $count: 'count' }
])
the execution of the route that uses the call is max 100ms.
When I comment it in the call jumps to approx 1100ms.
Is there someway to get the pagination data I am looking for without a significant increase in request time? 10X seems quite large.

Using Mongo Geospatial queries on lots of data

I am using a Mongo database with mongoose in Nest, a typescript server framework.
I have 2 mongo collections, one contains 20,000 user locations. The other collection contains 10,000 Point of Interests gathered from Google Places API.
I want to now find intersections between gathered locations and these places (which contain a lat and lng GeoJSON point).
In other words, I am looking to see where in relation to these POI's users were.
Currently, I have an async method that will find all the locations that are near a point, using the nearSphere operator.
Then I think the next step will be to then iterate over each place (10,000 of them) in the mongo collection and run this method on each location. That way I will have a list of which POI's were 'nearby' when that specific location was caught.
Is there a better way to do this? With regards to performance I believe this way will struggle. I cannot find a mongo geospatial query that will let me compare 2 sets of locations together.
Get all locations near point
async findAllNearPlace(coords): Promise<Location[]> {
return await this.locationModel.find(
{
location:
{ $nearSphere:
{
$geometry: { type: "Point", coordinates: coords },
$minDistance: 0,
$maxDistance: 100
}
}
}
);
}
Each POI - check locations:
async findUsersInProximity(places): Promise<Location[]> {
const locations = [];
let i = places.length - 1;
while (i > 0) {
await this.findAllNearPlace(
places[i].location.coordinates
).then(intersectingLocations => {
locations.push(...intersectingLocations);
i--;
});
}
return await locations;
}
As expected, the performance of this is poor and takes minutes.
What you can probably do, is to make an aggregate function with a lookup, I did not test it, and I don't know for sure if it is a better performance, but you can do something similar to the following:
let pipeline = [
{
$geoNear: {
includeLocs: "location",
distanceField: "distance",
near: { type: 'Point', coordinates: "$$point" },
maxDistance: 20,
spherical: true
}
}
];
UsersModel.aggregate([{
$lookup : {
from : 'locations',
let : {point : '$address'}, //whatever the field for the coordinates is
pipeline ,
as : 'places'
}
}])