Is there a parameter that I can add to the search which will limit the results to addresses within Europe or US ?
I'm using js to access the geocoding api, once the end user has typed in n characters I'm using that as the search query. So far I have this:
return new Promise((resolve, reject) => {
let geoCoder = this.platform.getSearchService()
let geoCodingParameters = {
q: searchString,
jsonattributes: 1
}
geoCoder.geocode(
geoCodingParameters,
(response) => { resolve(response.items) },
reject
)
})
Which works just fine, but I'd prefer not to show addresses which aren't relevant to the end users' region.
You should be able to use the parameter in to provide an ISO 3166-1 alpha-3 countryCode such as USA to limit results to a specific region. For example:
let geoCodingParameters = {
q: searchString,
in: 'countryCode:USA',
jsonattributes: 1
}
The JS API wraps the Geocoding & Search API. You can check out all parameters in the API Reference.
Related
I have angular-meteor app that needs Material md-autocomplete from a collection with 53,296 documents with angularUtils.directives.dirPagination but this amount of data make my browser hang.
I'm publishing the collection with:
Meteor.publish('city', function (options, searchString) {
var where = {
'city_name': {
'$regex': '.*' + (searchString || '') + '.*' ,
'$options': 'i'
}
};
return City.find(where, options);
});
I subscribe with:
subscriptions: function () {
Meteor.subscribe('city');
this.register('city', Meteor.subscribe('city'));
}
and have pagination on controller :
$scope.currentPage = 1;
$scope.pageSize = 100;
$scope.sort = {city_name_sort : 1};
$scope.orderProperty = '1';
$scope.helpers({
city: function(){
return City.find({});
}
});
but it takes a long time to load and its make chrome stop working.
You already have most of the server-side searching done because your search is running inside a subscription. You should make sure that the city_name field is indexed in mongo! You should only return that field to minimize data transfer. You can also simplify your regex.
Meteor.publish('city', function (searchString) {
const re = new RegExp(searchString,'i');
const where = { city_name: { $regex: re }};
return City.find(where, {sort: {city_name: 1}, fields: {city_name: 1}});
});
What I've found helps with server-side auto-complete is:
Don't start searching until the user has typed 3 or 4 characters. This drastically narrows down the search results.
Throttle the search to only run every 500ms so that you're not sending every character to the server because then it has to keep re-executing the search. If the person is typing fast the search might only run every 2 or 3 characters.
Run the same .find() on the client that you're running on the server (instead of just querying for {}). That's just good practice since the client-side collection is the union of all subscriptions on that collection, there might be documents there that you don't want to list.
Lastly I don't know why you're subscribing twice here:
subscriptions: function () {
Meteor.subscribe('city');
this.register('city', Meteor.subscribe('city'));
}
only one of those Meteor.subscribe('city') calls is necessary.
Here is a link to the same question.
I would however like to have this question answered using Google Geocode.
Can someone please provide me with the code to do the following, using Meteor and Blaze.
Enter zip code and return array of zip codes within 10 kilometers of that zip code.
Search collection users for fields profile.zipcode and display users matching zip codes in the array.
Thank you very much!
The Geocoder gets you the location from the text string, now you have to pass this location information to your places functionality. I have wrapped the google places code inside a function and call it from geocoder.
var address = '12 Crest View Ct';
geocoder.geocode({'address': address},
function(results, status) {
if(status == google.maps.GeocoderStatus.OK){
loc = results[0].geometry.location;
var bounds = new google.maps.LatLngBounds();
document.write(bounds.extend(results[0].geometry.location));
map.fitBounds(bounds);
new google.maps.Marker({
position:results[0].geometry.location,
map: map
});
place(loc); //here is the function call
}
}
);
I have a Meteor app that pulls data in from an external api. For simplicity sake we'll say something like...
var foo = Meteor.http.call("GET", "api-endpoint-url-here");
And inserts the data into a collection...
Bar = new Mongo.Collection("bar");
Bar.insert({
Results: foo
});
The json array (e.g. foo) includes a number of individual records each of which has it's own id number and corresponding data. I'm presently using JSON.parse to establish my array and then looping through the array to create individual documents using _.each
var fooParsed = JSON.parse(foo.content)
var fooArray = fooParsed.results;
_.each(fooArray, function(records) {
Bar.insert ({
record: record
});
});
For now it's crude but that aside - I've heard using forEach is preferred for performance. Is that the general consensus and any thoughts on how to streamline this and implement such a loop in this instance?
in case it's helpful to someone else in the future - here's where this netted out
fooArray.forEach(function(item) {
Bar.insert({
_id: item.id,
description: description,
});
});
I'm having trouble configuring the waitOn portion of a route where one of the subscription's parameters is determined by the value from a doc that comes from a different subscription.
The collections in play are Candidates and Interviews. An interview will have one and only one candidate. Here's some sample data:
candidate = {
_id: 1
firstName: 'Some',
lastName: 'Developer'
//other props
};
interview = {
_id: 1,
candidateId: 1
//other props
};
The route is configured as follows.
this.route('conductInterview', {
path: '/interviews/:_id/conduct', //:_id is the interviewId
waitOn: function () {
return [
Meteor.subscribe('allUsers'),
Meteor.subscribe('singleInterview', this.params._id),
// don't know the candidateId to lookup because it's stored
// in the interview doc
Meteor.subscribe('singleCandidate', ???),
Meteor.subscribe('questions'),
Meteor.subscribe('allUsers')
];
},
data: function () {
var interview = Interviews.findOne(this.params._id);
return {
interview: interview,
candidate: Candidates.findOne(interview.candidateId);
};
}
});
The problem is that I don't have a candidateId to pass to the singleCandidate subscription in the waitOn method because it's stored in the interview doc.
I've thought of two possible solutions, but I don't really like either of them. The first is to change the route to something like /interviews/:_id/:candidateId/conduct. The second is to denormalize the data and store the candidate's info in the interview doc.
Are there any other options to accomplish this besides those two?
You may get some ideas by reading this post on reactive joins. Because you need to fetch the candidate as part of the route's data, it seems like the easiest way is just to publish both the interview and the candidate at the same time:
Meteor.publish('interviewAndCandidate', function(interviewId) {
check(interviewId, String);
var interviewCursor = Interviews.find(interviewId);
var candidateId = interviewCursor.fetch()[0].candidateId;
return [interviewCursor, Candidates.find(candidateId);];
});
However, this join is not reactive. If a different candidate gets assigned to the interview, the client will not be updated. I suspect that isn't a problem in this case though.
You can change your publish function singleCandidate to take interviewId as paramater instead of candidateId and pass this.params._id
I had similar problem I managed to solve it via callback in subscribe
http://docs.meteor.com/#/basic/Meteor-subscribe
For example you have user data with city ids, and you need to get city objects
waitOn: ->
router = #
[
Meteor.subscribe("currentUserData", () ->
user = Meteor.user()
return unless user
cityIds = user.cityIds
router.wait( Meteor.subscribe("cities", cityIds)) if cityIds
)
]
I tried to search for all cities within a visible map's bounds. How can I do that?
Below is what I tried to do:
$.fn.gmap3.geocoder.geocode({ 'address': 'Georgia' }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
globalMap.setCenter(results[0].geometry.location);
var resultBounds = new google.maps.LatLngBounds(
results[0].geometry.viewport.getSouthWest(),
results[0].geometry.viewport.getNorthEast()
);
globalMap.fitBounds(resultBounds);
// get cities in the map
var service = new google.maps.places.PlacesService(globalMap);
var request = {
bounds: resultBounds,
types: ['locality']
};
service.search(request, function (results, status) {
debugger;
});
}
});
But the result is ZERO_RESULTS. Maybe the reason is that the results are restricted to a radius of 50.000 meters?
Anyone knows how to solve my problem? Thanks a lot.
--UPDATE--
Thank, Sean, for reading my post carefully and give detail feedback.
This is how I refer to the lib:
src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"
I also added more detail to the geocode function to get more precise result. But I still don't get the results I want.
Check the list in this page: https://developers.google.com/places/documentation/supported_types, I realize that almost all items in the first list returns values but not for the second list. The only item return value is 'political' and it returns only 1 instead of 20.
This is my code after modifing:
this.setCenterByAddress = function (address, region) {
$.fn.gmap3.geocoder.geocode({ 'address': address, 'region': region }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
globalMap.setCenter(results[0].geometry.location);
var resultBounds = new google.maps.LatLngBounds(
results[0].geometry.viewport.getSouthWest(),
results[0].geometry.viewport.getNorthEast()
);
globalMap.fitBounds(resultBounds);
// get cities in the map
var service = new google.maps.places.PlacesService(globalMap);
var request = {
bounds: resultBounds,
types: ['country',
'administrative_area_level_1',
'administrative_area_level_2',
'administrative_area_level_3',
'colloquial_area',
'country',
'floor',
'geocode',
'intersection',
'locality',
'natural_feature',
'neighborhood',
'political',
'point_of_interest',
'post_box',
'postal_code',
'postal_code_prefix',
'postal_town',
'premise',
'room',
'route',
'street_address',
'street_number',
'sublocality',
'sublocality_level_4',
'sublocality_level_5',
'sublocality_level_3',
'sublocality_level_2',
'sublocality_level_1',
'subpremise',
'transit_station']
};
service.search(request, function (results, status) {
debugger;
});
}
});
}
MORE INFO: The same value return even when location and radius is used. And I use free map and receive "OVER_QUERY_LIMIT" all the time.
You shouldn't be limited to 50,000 meters unless you use the location and radius option, which you are not; you are using bounds. I suggest backing out a level and digging into the results that are returned from the starting call to geocode, because your usage of the PlacesService appears to be correct. What are the values internal to the resultBounds object? I also notice that you aren't using region biasing when you call the geocoder and it may be that "Georgia" is not sufficiently specific. For example, do you mean the region within the Russian Federation or the US state? And I'm not sure what URL you are using to load the Google Maps API & places library, but that could also be effecting your results.
I'd double-check the results coming back from the geocoder, because unless I am missing something, it looks like your basic approach is sound.
You can't return more than two near by localities around a particular latitude-longitude with Geocoding API/Places API
Please see this thread on Google Places API forum
This is not possible with the Google Places API as political results
such as locality, neighbourhood and sublocality are returned to
identify the area of the request and are limited to two per request.