mongoDB remove sub-array - php

Ok is there a quick way to remove the follwoing though PHP mongodb
here is our mongoDB row
{
"today":""
"session": "6266262626",
"products": [
{
"barcode": "27788822",
"item": "village day ticket",
"price": 1315,
"qty": "3"
},
{
"barcode": "8544122",
"item": "village night ticket",
"price": 1433,
"qty": "1"
}
]
}
I would like to delete the product
{
"barcode": "8544122",
"item": "village night ticket",
"price": 1433,
"qty": "1"
}
I know how to update, and insert but cant figure out how to delete it.

here is a mongo command to delete the item, given its barcode :
db.collection.update({session:'6266262626'},{ $pull: { products: { barcode : '8544122' } }})
If you want to delete multiple items from the products array, given an array of barcodes :
db.collection.update({session:'6266262626'},{ $pull: { products: { barcode : {$in : ['27788822','8544122'] } } }})
I don't know the PHP equivalent of those commands, but here is a related question using $pull and PHP which may help :
MongoDB pull array element from a collection
this question is pretty old, but deleting multiple array items in a single query was giving me trouble today, and in my case the above is working out, so maybe it will help somebody else, thanks.

Reading the docs is your friend. Use the positional operator
http://www.mongodb.org/display/DOCS/Updating#Updating-The%24positionaloperator

Related

Laravel - Eloquent to Json, and then sortBy on json object not working

I have this json value that I want to be sorty but for some reason it's not working.
[
{
"id": 15028,
"order_id": 342,
"user_id": 3,
"status": "1",
"priority": "1",
"donedate": null,
"user": {
"id": 3,
"name": "Max"
}
},
{
"id": 15030,
"order_id": 341,
"user_id": 4,
"status": "2",
"priority": "1",
"donedate": null,
"user": {
"id": 4,
"name": "Jon"
}
}
]
This jSon structure is the result of Laravel eloquent object conversion using $object->toJson();
Now I keep this output in my Redis cache. What I want is to when the status and or priority of any order gets changed then I want to sort this jSon and store it back in Redis.
$order_list = collect($json_decoded_with_updated_values);
$order_list = $order_list->sortBy('status')->sortBy('priority');
Redis::set(\GuzzleHttp\json_encode($stich_list_in_collection));
Redis::set("orders_list", $orders_list, 302400);
However, I don't get a sort list. What I want to achieve is that, just like I would run two to three orderBy on an eloquent model like orderBy('status')->orderBy('priority')->get() .. I want to run the same two sortings on this json list.
Thanks in advance.
I figured it out. Actually we don't need to have a call-back as suggested by #brokedid. We can do it like following.
$order_list->sortBy('status')->sortBy('priority')->values()->all();
So I was missing the "->values()->all()" part. I hope if any one runs into the same problem in future, they can get a hint from this.
If you want to sort by multiple Fields, then you could try to sort with a callback-method:
$orderedList = $unorderedList->sortBy(function($item) {
return $item->priority.'-'.$item->status;
});
I wonder what's the result when you choose a different sort direction.
$order_list = $order_list->sortByDesc('status');

advanced search with ElasticSerach

I've create a small application with PHP and I use ES.
My request is good, but I've got the good result.
My request look-like that:
link:9200/index/_search?from=0&size=130&q=try:'yes'
%2Bbrand:'BMW' %2Bmodel:'SERIE 5' %2Bprice:[500 TO 700000]
When I send this query, ES reply me with model 'SERIE 3' and 'SERIE 5', it's great, but when I send this query, I would like to recover only 'BMW' and 'SERIE 5'.
How can I fix this?
First, you should take a look at the documentation to be more familiar with these notions (analyze / difference between query and filters) which are very important for a good use of ElasticSearch. You can find a good getting started documentation here.
Your problem is that your "model" field is a string, which by default is analyzed using the standard analyzer.
It outputs 2 tokens because of the whitespace in the model name as you can see if you use the _analyze endpoint :
GET _analyze?analyzer=standard&text='Serie 5'
{
"tokens": [
{
"token": "serie",
"start_offset": 1,
"end_offset": 6,
"type": "<ALPHANUM>",
"position": 1
},
{
"token": "5",
"start_offset": 7,
"end_offset": 8,
"type": "<NUM>",
"position": 2
}
]
}
On top of that, you're using a query and though will return all results matching even partially. So, you're certainly having the two cars in your results, but the "SERIE 5" car must be the first (as it matches better) than the car "SERIE 3", which is represented by a higher _score attribute.
You need to use a term filter which will return only the documents containing the term value you provided.
However, as it works on terms, you have to change the mapping of your field to "not_analyzed" like this to keep it as it is :
PUT /test/car/_mapping
{
"properties":{
"model":{
"type": "string",
"index":"not_analyzed"
}
}
}
Finally, the search request will be something like this (with price criteria as range filter and the use of a and filter to combine both) :
GET /test/car/_search
{
"query": {
"filtered": {
"filter": {
"and": {
"filters": [
{
"term": {
"model": "Serie 3"
}
},
{
"range": {
"price": {
"from": 500,
"to": 70000
}
}
}
]
}
}
}
}
}
Your query (url_decoded) looks like
link:9200/index/_search?from=0&size=130&q=try:'yes' +brand:'BMW' +model:'SERIE 5' +price:[500 TO 700000]
I think you are using '+' incorrectely, so that it is doing or operation for your query,
If you want to get with try:yes, brand:BMW and model:SERIE 5 then you have to join these query by AND keyword.
like.
link:9200/index/_search?from=0&size=130&q=try:'yes'
AND brand:'BMW' AND model:'SERIE 5' AND price:[500 TO 700000]
And you should be aware of choosing analyzer (in mapping of fields), so that things are indexed as you want.
It will work, Thanks
Reference

find() query MongoDB for php

Hi i am using mongoDb for my new project. I am trying to find values from mongodb database.
My mongoDB database collection name is: test and json format is below
{
"College": [
{
"name": "tamy",
"roll_no": "1"
},
{
"name": "abhi",
"roll_no": "2"
},
{
"name": "jack",
"roll_no": "3"
}
],
"School": [
{
"name": "zack",
"roll_no": "1"
},
{
"name": "mac",
"roll_no": "2"
},
{
"name": "john",
"roll_no": "3"
}
]
}
**And i want to find the name:abhi from test collection **
and my mongodb find query in php
$criteria = array(
'College'=> array(
'name'=> 'abhi'
));
$cursor = $collection->find($criteria);
but its not returning any value.
if i am displaying in php by using print_r.
print_r(iterator_to_array($cursor));
displaying empty array()
I need output like this:
name : jack
roll_no : 3
plz help me..
The key "College" is an array, your trying to treat it as a "subdocument" (but that wouldnt allow for multiple colleges to be stored)
You want the elemMatch keyword here I believe: http://docs.mongodb.org/manual/reference/operator/query/elemMatch/
EDIT: After looking at this again, I think you have your structure a little out of whack. How many "students" will there be per college or school? Keep in mind each parent document can not exceed 10mb, and when you select a document, the entire document must be sent back across the connection (unless you are using aggregate or map/reduce. I would think you may want to have a collection of Persons and then a key associating a person to... something else.

Populate a multi dimensional array using mySQL query involving relational tables

This might be fairly simple for the experts but I need help as a newbie. I have the following three tables which has items & attachments. I would like to have these data populated into a multi dimensional array as given in the result section below (in JSON format).
Tables - columns
items
- itemID
- itemTitle
- catID
attachments
- attachmentID
- itemID
- attachmentFilename
Considering there are two items in the database with the first item related to 2 attachments and the second item related to 3 attachments, this is how I would like to see the result:
{
"items": [{
"item": {
"itemID": "1",
"itemTitle": "The first item",
"attachments": [{
"attachment": {
"attachmentFilename": "The First attachment.att",
"attachmentID": "1"
},
"attachment": {
"attachmentFilename": "The Second attachment.att",
"attachmentID": "2"
}
}]
}
},
{
"item": {
"itemID": "2",
"itemTitle": "The Second item",
"attachments": [{
"attachment": {
"attachmentFilename": "The Third attachment.att",
"attachmentID": "3"
},
"attachment": {
"attachmentFilename": "The Fourth attachment.att",
"attachmentID": "4"
},
"attachment": {
"attachmentFilename": "The Fifth attachment.att",
"attachmentID": "5"
}
}]
}
}]
}
I would like to know how I can code in php such that I will get the above result. Thank you very much in advance.
If you really get the data to insert in JSON, take a look at json_decode.
Once your data has been stored in a variable you can loop through it with foreach and for each loop insert the data appropriately.

Mongodb nested array search

document structure example is:
{
"dob": "12-13-2001",
"name": "Kam",
"visits": {
"0": {
"service_date": "12-5-2011",
"payment": "40",
"chk_number": "1234455",
},
"1": {
"service_date": "12-15-2011",
"payment": "45",
"chk_number": "3461234",
},
"2": {
"service_date": "12-25-2011",
"payment": "25",
"chk_number": "9821234",
}
}
}
{
"dob": "10-01-1998",
"name": "Sam",
"visits": {
"0": {
"service_date": "12-5-2011",
"payment": "30",
"chk_number": "86786464",
},
"1": {
"service_date": "12-15-2011",
"payment": "35",
"chk_number": "45643461234",
},
"2": {
"service_date": "12-25-2011",
"payment": "20",
"chk_number": "4569821234",
}
}
}
In PHP i want to list all those "visits" information (and corresponding "name" ) for which payment is less than "30".
I want to print only the visits with "payment" < "30" not others. Is such query possible, or do i have to get entire document first using search and then use PHP to select such visits??
In the example document, the "payment" values are given as strings which may not work as intended with the $lt command. For this response, I have converted them to integers.
Wildcard queries are not possible with MongoDB, so with the given document structure, the key (0,1,2, etcetera) of the sub-document must be known. For instance, the following query will work:
> db.test.find({"visits.2.payment":{$lt:35}})
However,
> db.test.find({"visits.payment":{$lt:35}})
Will not work in this case, and
> db.test.find({"visits.*.payment":{$lt:35}})
will also not return any results.
In order to be able to query the embedded "visits" documents, you must change your document structure and make "visits" into an array or embedded documents, like so:
> db.test2.find().pretty()
{
"_id" : ObjectId("4f16199d3563af4cb141c547"),
"dob" : "10-01-1998",
"name" : "Sam",
"visits" : [
{
"service_date" : "12-5-2011",
"payment" : 30,
"chk_number" : "86786464"
},
{
"service_date" : "12-15-2011",
"payment" : 35,
"chk_number" : "45643461234"
},
{
"service_date" : "12-25-2011",
"payment" : 20,
"chk_number" : "4569821234"
}
]
}
Now you can query all of the embedded documents in "visits":
> db.test2.find({"visits.payment":{$lt:35}})
For more information, please refer to the Mongo documentation on dot notation:
http://www.mongodb.org/display/DOCS/Dot+Notation+%28Reaching+into+Objects%29
Now on to the second part of your question: it is not possible to return only a conditional sub-set of embedded documents.
With either document format, it is not possible to return a document containing ONLY the sub-documents that match the query. If one of the sub-documents matches the query , then the entire document matches the query, and it will be returned.
As per the Mongo Document "Retrieving a subset of fields"
http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields
We can return parts of embedded documents like so:
> db.test2.find({"visits.payment":{$lt:35}},{"visits.service_date":1}).pretty()
{
"_id" : ObjectId("4f16199d3563af4cb141c547"),
"visits" : [
{
"service_date" : "12-5-2011"
},
{
"service_date" : "12-15-2011"
},
{
"service_date" : "12-25-2011"
}
]
}
But we cannot have conditional retrieval of some sub documents. The closest that we can get is the $slice operator, but this is not conditional, and you will have to first know the location of each sub-document in the array:
http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements
In order for the application to display only the embedded documents that match the query, it will have to be done programmatically.
You may try:
$results = $mongodb->find(array("visits.payment" => array('$lt' => 30)));
But i don't know if it will work since visits is an object. BTW judging from what you posted it could be transfered to array (or should since numerical property names tends to cause confusion)
try - db.test2.find({"visits.payment":"35"})

Categories