MongoDB spatial query opposite of $geoIntersect, outside of polygon - mongodb

Is it possible to perform a query where a point is outside a polygon?
I'm not really sure how to word my question, but I'm trying to do this with my query
I want to check if location A (Pickup) is in inside, and location B (dropoff) is outside
I thought of using $ne and $not but I get the error "unknown top level operator: $not"
$pickupPoint = [
'type' => 'Point',
'coordinates' => [
floatval($this->item['longitude']),
floatval($this->item['latitude'])
]
];
$dropPoint = [
'type' => 'Point',
'coordinates' => [
floatval($this->item['longitude']),
floatval($this->item['latitude'])
]
];
// Is in pickup, but outside dropoff
$pickupNotDropoff = [
'$and' => [
[
'Pickup' => [
'$geoIntersects' => [
'$geometry' => $pickupPoint,
]
]
],
[
'$not' => [
'Dropoff' => [
'$geoIntersects' => [
'$geometry' => $dropPoint,
]
]
]
]
]
];
Sample of data

Related

Query on the basis of empty array and non existing field with other conditions in expr

I have documents like
{
'_id': ...
'registration_temp_perm_no' => 'SIEI/216/2020',
'first_name' => 'Azra',
'last_name' => 'Ali'
},
{
'_id': ...
'registration_temp_perm_no': ....
'first_name': ...,
'last_name' : ...,
'transport_details' : [
{
...
status : "Inactive"
}
]
},
{
'_id': ...
'registration_temp_perm_no':...
'first_name' : ....
'last_name': .....,
'transport_details': []
}
Note that the documents are created/updated via front end functionalities in the following three ways
where embedded document 'transport_details' does not exist at all.
where embedded document 'transport_details' contains empty array
where embedded document 'transport_details' may contain multiple sub arrays
Now I want to fetch those documents where the status of last sub array is "Inactive" or "Requested" and where the sub array "transport_details" doesn't exist and "transport_details" is empty.
I have written query like
$query = array(
'$or' => array(
array("first_name" => new MongoDB\BSON\Regex($arg, 'i')),
array("middle_name" => new MongoDB\BSON\Regex($arg, 'i')),
array("last_name" => new MongoDB\BSON\Regex($arg, 'i')),
array("registration_temp_perm_no" => $arg)
),
"schoolId"=> new MongoDB\BSON\ObjectID($this->schoolId),
'$expr' => [
'$or' => [
['transport_details' => ['$exists' => false]],
['transport_details' => ['$size' => 0]],
['$eq'=> [['$arrayElemAt' => ['$transport_details.status', -1]], "Requested"]],
['$eq'=> [['$arrayElemAt' => ['$transport_details.status', -1]], "Inactive"]],
]
]
);
If we remove the lines ['transport_details' => ['$exists' => false]], ['transport_details' => ['$size' => 0]], the query is able to fetch those documents where the status of last sub array is "Inactive" or "Requested" otherwise it does not work.
When you use $expr, all next operators should have Aggregation-expressions syntax. Check full list here
You need to change
['transport_details' => ['$exists' => false]],
['transport_details' => ['$size' => 0]]
to
['$eq'=> ['$transport_details', undefined]], //equivalent to {$exists:false}
['$eq'=> [['$size' => '$transport_details'], 0]] // $size returns number, we compare numbers
If we apply $IfNull operator, we combine "no exist" + "empty array" into single condition.
Try this one:
db.collection.find({
... your extra conditions here
$expr: {
$or: [
{
$eq: [
{
$size: {
$ifNull: [
"$transport_details",
[]
]
}
},
0
]
},
{
$eq: [
{
$arrayElemAt: [
"$transport_details.status",
-1
]
},
"Requested"
]
},
{
$eq: [
{
$arrayElemAt: [
"$transport_details.status",
-1
]
},
"Inactive"
]
}
]
}
})
MongoPlayground

Filter on projection not working in mongodb

I have done aggregation query on student table with activity table which gives the desired fields except one field i.e "ActivityForMediumSize". This field comes empty.
The code is
$query = ["is_temp_deleted"=>0, "funRun" => "Yes"];
$pipeline = array(
array(
'$match' => $query
),
array(
'$lookup' => array(
'from' => 'studentTbl',
'localField' => '_id',
'foreignField' => 'activity_details.activityId',
'as' => 'studentsOfActivities'
)
),
['$lookup'=> [
'from'=> 'studentTbl',
'localField' => 'academic_year_Id',
'foreignField' => 'studentsOfActivities.academic_year_Id',
'as'=> 'Students'
]],
['$project' => [
'_id' => 1.0,
'activityName' => 1.0,
'activityTime' => 1.0,
'activityDate' => 1.0,
'funRun' => 1.0,
'Students' => 1.0,
'studentsOfActivities' => 1.0,
'studentsOfWeekgroup' => [
'$filter' => [
'input' => '$Students',
'as' => 'item',
'cond' => [
'$eq' => ['$$item.academic_year_Id', new MongoDB\BSON\ObjectID($this->id)],
]
]
],
'ActivityForMediumSize' => [
'$filter' => [
'input' => '$studentsOfActivities',
'as' => 'item',
'cond' => [
'$eq' =>['$$item.activity_details.-1.shirtSize', 'M'],
]
]
],
'StudentCountPerActivity'=>['$size'=>'$studentsOfActivities'],
// 'MediumCount'=>['$size'=>'$countForMedium']
]],
);
$cursor = $this->db->activitiesTbl->aggregate($pipeline)->toArray();
I have checked in console that data in "studentsOfActivities" appears like
0 =>
"_id": ObjectId("5bf518378d03ec0b2400536f"),
"ssn_Last_four": "0001",
"first_name": "Thomas",
"activity_details": [
{
"studentId": ObjectId("5bf518378d03ec0b2400536f"),
"funrun": "Yes",
"weekgroupId": ObjectId("5bf50bd48d03ec0b2400536d"),
"activityId": ObjectId("5c10a0e08d03ec1834001c6d"),
"attending": "Yes",
"id": ObjectId("5c10e5ae3250041188005dde")
},
{
"studentId": ObjectId("5bf518378d03ec0b2400536f"),
"funrun": "Yes",
"weekgroupId": ObjectId("5bf50bd48d03ec0b2400536d"),
"activityId": ObjectId("5c10a0e08d03ec1834001c6d"),
"attending": "Yes",
"shirtSize": "L",
"id": ObjectId("5c13338032500409f4007cf3")
}
]
1=>
"_id": ObjectId("5bf518378d03ec0b2400536e"),
....
....
The embedded document "activity_details" contains student's all the activities and the last element of it is considered active one i.e why I have used -1 in the above code.
Now in projection "ActivityForMediumSize" I am trying find those students who have selected shirtSize: "M". The filter on projection "ActivityForMediumSize" is not working. Please help !!!
Note that there are some students where the last activity inside "activity_details" which does not contain "shirtSize" field.
I guess "is not working" means you have an empty array. It's because you cannot refer to the last element of an array just by "-1". Instead you need to use array operators to get the last element. For example it can be a combination of arrayElemAt and slice so the filter condition can look like :
$eq: [
{ $let: {
vars: {
last: { $arrayElemAt: [
{ $slice: [ '$$item. activity_details', -1 ] },
0
] }
},
in: '$$last.shirtSize'
} },
'M'
]
It's in js syntax but it should be trivial to translate to php.

Error message lookup pipeline must be a string, is type array

I am using mongodb 3.6 version.
I have vehicle table with documents like
{
"_id": ObjectId("5b976220d2ccda12fc0050fb"),
"VehicleNumber": "JK 678",
"NumberOfSeats": "47",
}
{
"_id": ObjectId("67976220d2ccda12fc005068"),
"VehicleNumber": "JK 779",
"NumberOfSeats": "47",
}
I have route table with data like
{
"_id": ObjectId("5b7fb426d2ccda11fc005185"),
"Name": "New Jersey City",
"VehicleDetails": [
{
"VehicleEntryId": "b8d0d2b5-8f32-6850-4d79-34ed79138d6d",
"VehicleId": ObjectId("5b976220d2ccda12fc0050fb"),
...
"Status": "Active"
},
{
"VehicleEntryId": "b8d0d2b5-8f32-6850-4d79-34ed79138568",
"VehicleId": ObjectId("67976220d2ccda12fc005068"),
...
"Status": "Active"
}
],
...
}
I have written mongodb aggregation query like
$cursor = $this->collection->aggregate([
['$match' => ["_id" => new MongoDB\BSON\ObjectID('5b7fb426d2ccda11fc005185')]],
[
'$addFields' => [
'filteredIds' => [
'$map' => [
'input' => '$VehicleDetails',
'as' => 'item',
'in' => [
'$cond' => [
['$eq' => ['$$item.Status', 'Active']],
'$$item.VehicleId',
false
]
]
]
]
]
],
array(
'$lookup' => array(
'from' => 'VehicleTbl',
'$pipeline' => [
[ '$match'=> ["_id" => ['$in' => ['$$filteredIds'] ]]],
],
'as' => 'AllotedVehicleDetails'
)
),
])->toArray();
Basically I am trying to fetch all assigned vehicle to a particular route. So I first fetch all the actively alloted vehicle ids by using $addFeilds operator and putting them in "filteredIds" then in lookup I am trying to fetch vehicle informations from vehicle table using pipeline. The above code throws error message 'Uncaught exception 'MongoDB\Driver\Exception\RuntimeException' with message '$lookup argument '$pipeline: [ { $match: { _id: { $in: [ "$$filteredIds" ] } } } ]' must be a string, is type array' in' line no 32.
Please help!!!
use pipeline instead of $pipeline.
Example:
{
$lookup : {
'from' : 'vehicles',
let : { localFilterIds : '$filteredIds'},
pipeline : [
{'$match' : { $expr: { '$in' : [ '$_id', '$$localFilterIds' ] }} }
],
'as' : 'AllotedVehicleDetails'
}
}
Note: This is tested in mongoDb GUI Robo 3T.

aggregate function not working php codeigniter

I wrote a aggregate query to get data in mongodb. same query I need to run via php codigniter,
This is my mongodb query
db.states.aggregate([
{
$project: {
states: {
$filter: {
input: "$states",
as: "state",
cond: { $eq: [ "$$state.country_id", "101" ] }
}
}
}
}
])
same query i need to convert for php codignater. I have used this library to perform the db operarion.
I tried:
$pipeline = [
[
'$project' => [
'states' =>[
'$filter' => [
'input' => '$states',
'as' => 'state',
'cond' => [
'$eq' => [
'$$state.country_id' => $country_id
]
]
]
]
]
]
];
$result = $this->mongo_db2->aggregate('tb10_states', $pipeline);
But, its throw Message: Unrecognized expression '$$state.country_id'
Suggest me How to fix this.

how to convert aggregate to mapReduce using Laravel MongoDB by jenssegers

Right now, I have the below code in my laravel app. I'm running into this error: mongo1:27017: exception: aggregation result exceeds maximum document size (16MB). I read that I should use mapReduce instead of aggregate to avoid this issue but am unsure how to translate the below to mapReduce using Laravel MongoDB by jenssegers.
Here is my code using aggregate:
$email_duplicates = User::raw(function ($collection) {
return $collection->aggregate(
[
[
'$group' => [
'_id' => [
'email' => '$email',
],
'uniqueIds' => [
'$addToSet' => '$_id',
],
'count' => [
'$sum' => 1,
],
],
],
[
'$match' => [
'count' => [
'$gt' => 1,
],
],
],
],
[
'allowDiskUse' => true,
]
);
});
Can anyone help?