I am using the Moloquent model with Laravel 5.6. here is my collection record given below:-
{
"_id" : ObjectId("5afe619dbe0b8d0e5876b16b"),
"name" : "Central Park",
"categories" : [
"4d4b7105d754a06376d81259",
"4bf58dd8d48988d116941735",
"4bf58dd8d48988d119941735",
"4d4b7105d754a06376d81259",
"4bf58dd8d48988d116941735",
"4bf58dd8d48988d119941735",
"4d4b7105d754a06374d81259",
"4bf58dd8d48988d16d941735"
],
"loc" : {
"type" : "Point",
"coordinates" : [
88.4166612820784,
22.5835157504658
]
}
}
I am running this query from the Laravel controller.
$users = MongoTest::where('loc', 'near', [
'$geometry' => [
'type' => 'Point',
'coordinates' => [
$longitude,
$latitude,
],
],
'$maxDistance' => 10,
])->get();
print_r($users);
I am getting this error:-
error processing query: ns=tkit.testTree: GEONEAR field=loc maxdist=10 isNearSphere=0
Sort: {}
Proj: {}
planner returned error: unable to find index for $geoNear query
How can I solve this?
Create an index from the mongo shell. A 2sphere index is expected by the query using the $near or $nearSphere operator or geoNear command, or even the $geoNear aggregation pipeline stage.
The createIndex() method will do this for you, so just name your collection within the correct database:
db.collection.createIndex({ "loc": "2dsphere" })
Note that any API actually using the geoNear command really needs to update to one of the other mentioned query operators as this command is "deprecated" from MongoDB 4.0 onwards and will be removed.
Operations looking for "nearest" should use $near or $nearSphere, and those which want to return the "distance" should use the $geoNear pipelie stage instead.
Related
I want to index in my index buildings 2 types of documents: building & apartment.
A building can have several apartment, so I want to use parent/child relationships.
I use ES 7.10 and PHP with official PHP lib (elasticsearch/elasticsearch).
According to the doc (https://www.elastic.co/guide/en/elasticsearch/guide/current/parent-child-mapping.html), I have to use something like :
PUT index buildings
{
"mappings": {
"building": {},
"apartment": {
"_parent": {
"type": "building"
}
}
}
}
In my PHP I have :
$this->getClient()->indices()
->create([
'index' => 'buildings',
'body' => [
'mappings' => [
'building' => [],
'apartment' => [
'_parent' => [
'type' => 'building'
]
]
]
]
]);
Which throws the error:
Root mapping definition has unsupported parameters: [apartment: {_parent={type=building}}] [building: []]"}},"status":400}
Did I miss something?
Parent/type has been deprecated in favor of join type in Elasticsearch 7 as far as I remember, so this might be the reason you're getting the exception.
Link to docs: https://www.elastic.co/guide/en/elasticsearch/reference/current/parent-join.html
I have created query in mongoDB. In MongoChef this query produces more than 10 thousand records in less than 2 seconds. Now I want to execute this query in PHP.
So i don't know how to write query in php as I read various documents on internet but confused how to implement it.
db.PMS.aggregate(
[
{$project:
{EventTS:1,MainsPower:1,PanelID:1}
},
{$unwind:
{path:"$MainsPower",includeArrayIndex:"arrayIndex",preserveNullAndEmptyArrays:true}
},
{ $match: { "MainsPower":{$ne:null}}},
{ $match: { "EventTS":{$gt:new Date("2016-01-01")}}},
{$project:
{MainsPower:1,
PanelID:1,
timestamp:{"$add":
[{'$subtract' : ["$EventTS",new Date("1970-01-01")]},
{"$multiply":[60000,"$arrayIndex"]}
]}
}
}
]
);
You can use some resources available on the php official documentation. A mapping of sql queries in php to mongoDB queries in php can be found here.
Also I have a demo login and registration script at my github. You can view those in this repo.
If you use MongoDB PHP Library you should be able to do something similar to this:
$mongo = new MongoClient();
$database = $mongo->examples;
$collection = $database->PMS;
$pipeline = [
[
'$project' => [
'EventTS' => 1,
'MainsPower' => 1,
'PanelID' => 1,
]
],
[
'$unwind' => [
'path' => '$MainsPower',
'includeArrayIndex' => 'arrayIndex',
'preserveNullAndEmptyArrays' => true
]
],
...
];
$cursor = $collection->aggregate($pipeline);
I want to be able to store a json object in my ES index. Here's an example of what I'm trying to store (this a serialized model, a request body that is sent to ES):
"{"id":218,"name":"Test2","category_id":1,"address":"Pushkin street","phone":null,"site":null,"location":{"lat":64,"lon":70},"city":"Heaven","description":"Super company","tags":["#test1","#test2"]}"
When I try to store it (via the extension, of course), here's the error that ES returns:
"{"error":{"root_cause":[{"type":"mapper_parsing_exception","reason":"failed to parse [location]"}],"type":"mapper_parsing_exception","reason":"failed to parse [location]","caused_by":{"type":"illegal_argument_exception","reason":"unknown property [lat]"}},"status":400}"
It seems that I am unable to do so without having a specific type mapping, like in the docs:
https://www.elastic.co/guide/en/elasticsearch/reference/1.4/mapping-object-type.html
However, I don't seem to find a way to provide that mapping inside the model. The extension's documentation doesn't really say anything about it.
So, my question is: do I need it at all, and if I do, how?
Appreciate all feedback.
I'll assume your model is \yii\elasticsearch\ActiveRecord. You'll need to describe its attributes:
public function attributes()
{
return [
'name',
'category_id',
'address',
'phone',
'site',
'location',
'city',
'description',
'tags'
];
}
Don't forget to configure index() and type(). In the following example type is my_address.
Then you'll need to create an index with proper field mapping. Here's what your mapping should look like:
"mappings" : {
"my_address" : {
"properties" : {
"name" : { "type" : "string"},
"category_id" : { "type" : "integer"},
"address" : { "type" : "string"},
"phone" : { "type" : "string"},
"site" : { "type" : "string"},
"location" : { "type" : "geo_point"},
"city" : { "type" : "string"},
"description" : { "type" : "string"},
"tags" : { "type" : "string"}
}
}
}
Note three things:
Location is of type geo_point.
Tags are declared as string. This will also allow them to be arrays of strings.
I didn't include the id field. If it's unique, I suggest you just set your yii model's id to the necessary value ($model->primaryKey = '123'). Otherwise your ES model will have its internal id set to something like AVDXmfJ3Ou7LzqD1DDMj and also have an id field which is not very convenient.
I encourage you to take a closer look at the mappings - they are very important when it comes to configuring how exactly the strings are being analyzed.
UPDATE: You don't really describe the mapping anywhere in your model. Do it in a migration - similar to creating tables in SQL.
In case you using ElasticSearch ActiveRecord , you could define a method for setupMapping
Class BookIndex extends yii\elasticsearch\ActiveRecord
{
/**
* sets up the index for this record
*
*/
public static function setUpMapping()
{
$db = static::getDb();
//in case you are not using elasticsearch ActiveRecord so current class extends database ActiveRecord yii/db/activeRecord
// $db = yii\elasticsearch\ActiveRecord::getDb();
$command = $db->createCommand();
/*
* you can delete the current mapping for fresh mapping but this not recommended and can be dangrous.
*/
// $command->deleteMapping(static::index(), static::type());
$command->setMapping(static::index(), static::type(), [
static::type() => [
// "_id" => ["path" => "id", "store" => "yes"],
"properties" => [
'name' => ["type" => "string"],
'author_name' => ["type" => "string"],
'publisher_name' => ["type" => "string"],
'created_at' => ["type" => "long"],
'updated_at' => ["type" => "long"],
'status' => ["type" => "long"],
],
],
]);
}
}
Later on you just need to call this method any time you want to apply the new mapping.
I am attempting to make a Google like search using ElasticSearch and PHP. I have been reading a ElasticSearch book and I think I was to use simple_query_string query type that can take the keywords (or phrase) from a search box and try to find some of all of the terms entered.
I am using the PHP ElasticSearch library in my project and after connecting to my server I am trying to pass a $client->search($params) to my search to return a result.
I have this as my params array
$params =
[
'index' => 'letsmeetup',
'type' => 'person',
'body' =>
[
'query' =>
[
'simple_query_string' =>
[
'query' => $keywords,
'fields' => [
"first_name","last_name","bio","username","email_address","interests","skills"
]
]
]
]
];
I used a phrase like 'People who love php' and I get results. I tried 'real time web' (which is in my bio) as I get the correct result.
Problem is when I try 'Er', knowing there is a first_name of "Erin", or 'Neo', which I have "neo4j" in my bio, it's returning no results. Do I have the params array correct?
You need to use wildcards for these kind of queries
{
"query": {
"query_string": {
"fields": [ "first_name","last_name","bio","username","email_address","interests","skills"],
"query": "Er*"
}
}
}
This will match "Erin", "Eric", "Error" and so on.
You can find more information about Query String Syntax and wildcards here. https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#query-string-syntax
I hope this helps!
I'm trying to use Codeigniter with codeigniter-mongodb-library/tree/v2 in order to connect with mongo and Update documents with this structure:
{
"_id" : ObjectId("50fd8bd460e958aa38000002"),
"created_at" : 1358793684,
"updated_at" : 1358793684,
"is_active" : 0,
"memberships" : [
{
}
],
"first_models" : [
[ ]
],
"second_models" : [
[ ]
],
"pages" : [
[ ]
]
}
All I want is Update some document by it's given _id. Particularly I need to add elements inside "first_models" array. From my Codeigniter model I'm calling this:
$result = $this->mongo_db
->push(array('_id' => '50fd8bd460e958aa38000002'),array('first_models' => array('Some text here')))
->update($this->collections['sites']);
I'm getting this error when I try to Update one specific document:
Mod on _id not allowed
Seems there is some conflict with the given _id... I'm missing something and I don't know what :(
I'm using Mongodb 2.2.2 with Codeigniter 2.1.3, PHP5.4 and Apache2.
I was going in wrong direction with that. Finally #Rajan points me to right solution:
$updated = $this->mongo_db->where('_id', new MongoId($id))
->set($data)
->update('mycollection');
You can see, using set instead push, and referencing object id with new MongoId($id) :-)