MongoDB Geospatial query result not getting in order of Distance - geospatial

I am new to mongodb, trying to fetch result from mongodb using geospatial.
With this [http://jamesroberts.name/blog/2012/03/12/mongodb-geospatial-query-example-in-php-with-distance-radius-in-miles-and-km/][1] reference, I created 2d indexer on my collection.
I am getting result but not getting in sorted order of Distance.
I tried $near operator also but it returns 100 documents. I want all result near by given location under given miles
Can anyone please help me to get data in sorted order of distance?
$connection = new MongoClient( "mongodb://192.168.1.167" );
$dbname="mydb";
$collectionName="user";
$db = $connection->$dbname;
$collection = $db->$collectionName;
$lat="36.23304900";
$lon="-115.24228800";
$radius = 40;
$collection = $db->$collectionName;
$radiusOfEarth = 3956; //avg radius of earth in miles
$query = array('lnglat' =>array('$geoWithin' =>array('$centerSphere' =>array(array(floatval($lon), floatval($lat)), $radius/$radiusOfEarth))) ,'user_id' => "1234" ,'type'=>"my_type");
$cursor = $collection->find($query);

Try This:
$cursor = $collection->find($query);
$cursor->sort(array('distance' => -1));

Related

MongoDB: How to search in document array element

I'm sure this is a trivial question for the most of the Mongo users however, I was unlucky in finding the right answer.
I have a collection of documents like
{
_id:"2a1fd96c-73c5-49e1-a8ca-bd03a20c0197",
timestamp:1519725979178,
storeID:"xxx",
unitID: "yyy",
status:[1, 0, 1, 0],
_rev:"1-8019f22bf26b4d6cb99ae5460b3e0c65"
}
I need to find all documents that:
storeID = "xxx" AND unitID = "yyy" AND status[2] = 1
My filter entry that works with Compass
{'status.2': 1,storeID:'xxx',unitID:'yyy'}
However when I am trying to convert it into Js code
Model.find({'status.2': 1,storeID:'xxx',unitID:'yyy'})
Nothing is returned.
After a couple hours of pulling my hair out, I nailed the problem.
The filtering query
{'status.2':1,storeID:'xxx',unitID:'yyy'} and {'status.2':{$eq:1},storeID:'xxx',unitID:'yyy'} was actually okay.
Unfortunatelly, I used .find() along with Model instead of invoking it in collection scope:
let mongoose = require('mongoose'),
Schema = mongoose.Schema,
MyShema = new Schema({/* definition */}),
Model = mongoose.model('MyShema'),
filter = {'status.2':1,storeID:'xxx',unitID:'yyy'};
// BEFORE
let cursor = Model.find(fd); //returns total=0
// AFTER
let cursor = Model.collection.find(fd); //returns total=80
cursor.count()
.then(total=>console.log('total',total))
.catch(error=>console.log(error));
Somehow bizarrely when I removed 'status.2':1 from the filtering options, both instances of the cursor were returning an identical amount of documents.
The reason for that that was so pathetic - the status was declared in Schema as String whereas it should be obviously Array!

Different approach for pagination - LIMIT when using SQLSRV

I'm trying to make an instant pagination using SQLSRV and PHP, I have successfully did this using MySQL but unable to do so when using SQL Server as it does not support LIMIT.
I have the following codes working in MySQL and I wanted to apply the same thing in sqlsrv but since this is not possible, I'm looking forward in creating a different approach(code) to achieve this, can someone give me an idea or a walkthrough to make this happen please, thanks in advanced.
if(isset($_POST['page'])):
$paged=$_POST['page'];
$sql="SELECT * FROM `member` ORDER BY `member`.`member_id` ASC";
if($paged>0){
$page_limit=$resultsPerPage*($paged-1);
$pagination_sql=" LIMIT $page_limit, $resultsPerPage";
}
else{
$pagination_sql=" FETCH 0 , $resultsPerPage";
}
$result=sqlsrv_query($sql.$pagination_sql);
Try the following code, I hope you find it helpful
$paged = filter_input(INPUT_POST, 'page', FILTER_SANITIZE_NUMBER_INT);
//Initialize these values
$Table = 'your_tbl_name'; //Table name
$IndexColumn = 'pk_col_name'; //Primary key column
$resultsPerPage = '10'; //Page size
$Where = ''; //Optional WHERE clause, may leave empty
$Order = ''; //Optional ORDER clause, may leave empty
$top = ($paged>0) ? $resultsPerPage * ($paged-1) : 0 ;
$limit = 'TOP ' . $resultsPerPage ;
$pagination_sql = "SELECT $limit *
FROM $Table
$Where ".(($Where=="")?" WHERE ":" AND ")." $IndexColumn NOT IN
(
SELECT $IndexColumn FROM
(
SELECT TOP $top *
FROM $Table
$Where
$Order
)
as [virtTable]
)
$Order";
$result=sqlsrv_query($conn, $pagination_sql);

laravel 5 - paginate total() of a query with distinct

I have a query to get photos according to values in a pivot table, that stores the relation of "pics" and "tags":
#photos
$q = PicTag::select(DB::raw('distinct(pics.id)'),
'pics.url',
'pics.titel',
'pics.hits',
'pics.created_at',
'users.username',
'users.displayname')
->leftJoin('pics', 'pics.id', '=', 'pic_tag.pic_id')
->leftJoin('users','users.id','=','pics.user_id')
->whereIn('pic_tag.tag_id', $tagids);
if($cat)
$q->where('typ',$cat);
if($year)
$q->where('jahrprod',$year);
$pics = $q->orderBy('pics.id','desc')
->paginate(30);
The problem is, when for a certain photo multiple (same) tags are stored like "Tag", "tag" and "tAG". Then the same photo would be shown 3 times in my gallery. That is why I use the distinct in the query.
Then the gallery is ok, but $pics->total() does not show "87 photos" but for example "90 photos", because the distinct is not used in the pagination. In laravel 4, I used groupBy('pics.id'), but this did not seem to be the fastest query and with laravel 5 it gives me a total() count result of 1.
How could I get the right total() value?
I know it's an old subject but it could help some other people.
I faced the same problem and the only good solution (low memory cost) I found was to do the request in two times:
$ids = DB::table('foo')
->selectRaw('foo.id')
->distinct()
->pluck('foo.id');
$results = $query = DB::table('foo')
->selectRaw('foo.id')
->whereIn('foo.id', $ids)
->paginate();
I tried this with 100k results, and had no problem at all.
Laravel has issue in paginate of complex queries. so you should handle them manually . In laravel 5 I did it in 2 steps :
Step 1: repository method :
public function getByPage($page = 1, $limit = 10 , $provinceId , $cityId , $expertiseId)
{
$array = ['users.deleted' => false];
$array["users.approved"] = true;
$array["users.is_confirmed"] = true;
if($provinceId)
$array["users.province_FK"] = $provinceId;
if($cityId)
$array["users.city_FK"] = $cityId;
if($expertiseId)
$array["ONJNCT_USERS_EXPERTISE.expertise_FK"] = $expertiseId;
$results = new \stdClass();
$results->page = $page;
$results->limit = $limit;
$results->totalItems = 0;
$results->items = array();
$users= DB::table('users')
->distinct()
->select('users.*','ONDEGREES.name as drgree_name')
->join('ONJNCT_USERS_EXPERTISE', 'users.id', '=', 'ONJNCT_USERS_EXPERTISE.user_FK')
->join('ONDEGREES', 'users.degree_FK', '=', 'ONDEGREES.id')
->where($array)
->skip($limit * ($page - 1))->take($limit)->get();
//$users = $usersQuery>skip($limit * ($page - 1))->take($limit)->get();
$usersCount= DB::table('users')
->select('users.*','ONDEGREES.name as drgree_name')
->join('ONJNCT_USERS_EXPERTISE', 'users.id', '=', 'ONJNCT_USERS_EXPERTISE.user_FK')
->join('ONDEGREES', 'users.degree_FK', '=', 'ONDEGREES.id')
->where($array)
->count(DB::raw('DISTINCT users.id'));
$results->totalItems = $usersCount;
$results->items = $users;
return $results;
}
Step 2:
In my Search Controller :
function search($provinceId , $cityId , $expertiseId){
$page = Input::get('page', 1);
$data = $this->userService->getByPage($page, 1 , $provinceId ,$cityId , $expertiseId);
$users = new LengthAwarePaginator($data->items, $data->totalItems, 1 , Paginator::resolveCurrentPage(),['path' => Paginator::resolveCurrentPath()]);
return View::make('guest.search.searchResult')->with('users' ,$users);
}
It worked for me well!

complex entityframework query

I have two tables:
NewsRooms ( NrID[int] , NrName [string]);
RawNews( RnID [int], NrID[string]);
realtion is RawNews 1 * NewsRooms
so i use checkboxes for NewsRooms and save the ids as a string in RawNews like this ';1;2;'
now for example i have a list which contains some NrIDs . i want to select every RawNew which it's NrID contains any of the ids inside that list.
here is my code:
var temp = Util.GetAvailibleNewsRooms("ViewRawNews");
List<string> ids = new List<string>();
foreach (var item in temp)
ids.Add(";" + item.NrID.ToString() + ";");
model = db.RawNews.Where(r => r.NrID.Any(ids));
the line model = db.RawNews.Where(r => r.NrID.Any(ids)); is wrong and i don't know how to write this code. please guide me. thanks
ok guys, i found the solution myself so i post it here maybe some other guy need it some day!!
model = model.Where(r => ids.Any(i => r.NrID.Contains(i)));

How can I get distances from lucene geo(spatial) search with version 4.0.0?

I'm trying geo search function with the latest version of Lucene(4.0.0), the requirement is simple: getting the points inside a circle(the center and radius are passed in as query condition). I can not find the API that outputs the distance of each result to center, I have to calculate the distance after I get out the latitude and longitude of each result. anyone can help? the code is listed below:
SpatialContext sc = SpatialContext.GEO;
SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects,
sc.makeCircle(lo, la, DistanceUtils.dist2Degrees(dist, DistanceUtils.EARTH_MEAN_RADIUS_KM)));
Filter geo_filter = strategy.makeFilter(args);
try {
Sort chainedSort = new Sort(sfArray).rewrite(searcher);
TopDocs docs = searcher.search(new MatchAllDocsQuery(), geo_filter, 10000, chainedSort);
logger.debug("search finished, num: " + docs.totalHits);
for (ScoreDoc scoreDoc : docs.scoreDocs){
Document doc = searcher.doc(scoreDoc.doc);
double la1 = Double.parseDouble(doc.get("la"));
double lo1 = Double.parseDouble(doc.get("lo"));
double distance = getDistance(la1, lo1, la, lo); // have to calc distance by myself here, not cool
}
} catch (IOException e) {
logger.error("fail to get the search result!", e);
}
It's easy to get distance with Lucene 3.X, anyone familiar with geo(spatial) search with Lucene 4.0.0?
You have the lat & lon from the field; now you need to calculate the distance from the center point of the query circle. In your code, this would look like:
double distDEG = sc.getDistCalc().distance(args.getShape().getCenter(), lo1, la1);
double distKM = DistanceUtils.degrees2Dist(distDEG, DistanceUtils.EARTH_MEAN_RADIUS_KM);
Not bad; ehh?
(p.s. I wrote much of Lucene 4 spatial)

Resources