Find: Field value is contained within given text - mongodb

Let's say I have a collection of cars and each car has a property cars.make. Let's say some of those cars have a cars.make value of 'Toyota'. How do I find documents (using a MongoDB query) where the value cars.make is present in a given string, i.e. 'The Toyota Yaris was named car of the year in 2017.'

The answer, in PHP, because MongoDB Compass doesn't parse the JS-version of this filter and I'm lazy:
$results = $cars->find([
'$expr' => [
'$regexMatch' => [
'input' => 'The Toyota Yaris was named car of the year in 2017.',
'regex' => '$model',
'options' => 'i' // case-insensitive
]
]
]);

Related

TYPO3 11 TCA field 'type' => 'user' - Fetch child objects like inline

I'm trying to create my own TCA field user type to simply display some data in the typo3 backend of an objects child/children.
The thing is that when I fetch the children by query builder I would be returned an array with id's for its children instead of e.g. the title as defined in the tca of that object. As I want to display not the id but e.g. the title of that childs child I am stuck with a problem I don't know how to solve.
I've tried looking at the classes for the select elements (inline too) but when copying the beginning of the render function of it I already run into an "array key not defined" error for "items" (which is optional if a foreign_table is defined). The class I copied it from was \TYPO3\CMS\Backend\Form\Element\SelectSingleElement which I found by searching for AbstractFormElement which my class extends from too.
To make it clearer on what I want to achieve there's an example (I only used the parts that are important):
object1_tca.php:
'columns' => [
'object1' => [
'label' => 'object1',
'config' => [
'type' => 'user',
'renderType' => 'showChildData',
'foreign_table' => 'tx_ext_domain_model_object2',
'foreign_field' => 'object1',
'render_settings' => [
'childFields' => 'object3'
],
],
]
]
object2_tca.php:
'ctrl' => [
'title' => 'object2',
'label' => 'name',
'label_alt' => 'object3',
'label_alt_force' => true,
],
'columns' => [
'object3' => [
'label' => 'object3',
'config' => [
'type' => 'select',
'renderType' => 'selectSingle',
'foreign_table' => 'tx_ext_domain_model_object3',
'foreign_field' => 'object2',
],
],
]
object3_tca.php:
'ctrl' => [
'title' => 'object3',
'label' => 'name',
]
So the objects relations are as follows:
------------ ------------
| object 1 | ----- 1:m ----→ | object 2 |
------------ ------------
------------ ------------
| object 2 | ----- m:1 ----→ | object 3 |
------------ ------------
So, object2 will display as title its own name and the name of object3 that is selected. If I would change the field object2 of object1 configuration to a single select, I would also get that title for that child.
But I don't know how to fetch that title or that object2 data in my user type field.
In the end I want to do more with the data, group them by e.g. some field aso. This should also be applicable for different objects, so it's not the same repository or objects for the fields I want to use them for.
Can anyone help me? Is this even possible without having to fetch the children and the childrens children aso. from the database?
If you need more information I will provide whatever I can :) Any help is welcome. I feel like this should be easy but I'm stuck with even knowing where to look anymore. Thanks.

MongoDB aggregation match conditions fails

I have a problem with aggregation function:
this is a screen from MongoDB Compass:
Category structure:
{
'title' => 'Sport'
'articles' => [
{
'title' => 'My title'
'status' => 'published'
}
]
....
}
In the screen you can see a filter in order to get all categories with at least an article with status published.
In the result I always see also category with 'status' => 'draft'. I do not understand why this filter is not working.
How can I solve this?
Thanks

Find query with and operator in PHP

Hi i am working on backend of web application & want to find the documents from mongodb database that contain key active_status with value set to both 1 & 2. With mongodb PHP i am confused of how to find with both parameters in single query.
My query was this:
$mongoDb = MongoDbConnector::getCollection("endusers");
$endUserData = $mongoDb->find(array('active_status' => 1, '$and' => array('active_status' => 2)));
I have to fetch the users whose active_status should be 1 & 2. The above query doesnt seems to work. What is the right one for that?
Thanks on advance for quick response.
You have $and the wrong way around. Both arguments need to be included:
$endUserData = $mongoDb->find(array(
'$and' => array(
array( 'active_status' => 1 )
array( 'active_status' => 2 )
)
));
And since that would only make sense when looking for both elements within an array element, then you should instead use $all, which is shorter syntax:
$endUserData = $mongoDb->find(array(
'active_status' => array( '$all' => array(1,2) )
));
I should add that unless you intend to match a document like this:
{ "active_status" => [1,2] }
The you do not in fact want $and at all, but rather you want $or or better yet $in for multiple possible values on the same field:
$endUserData = $mongoDb->find(array(
'active_status' => array( '$in' => array(1,2) )
));
This matches documents like this:
{ "active_status": 1 },
{ "active_status": 2 }

How to keep orders in MongoDB?

In my MongoDB document I have object like this
[_id] => MongoId Object (
[$id] => 52a46b44aabacb5c218b4567
)
[results] => Array (
[http://google.com] => Array (
[position] => 1
[data] => 42672
)
[http://bing.com] => Array (
[position] => 2
[data] => 9423
)
[http://yandex.com] => Array (
[position] => 3
[data] => 5513
)
)
I would like to change data parameter in "bing.com" from 9423 to for instance 300. Moreover, I have to keep order of the sites. It have to looks like this
[_id] => MongoId Object (
[$id] => 52a46b44aabacb5c218b4567
)
[results] => Array (
[http://google.com] => Array (
[position] => 1
[data] => 42672
)
[http://bing.com] => Array (
[position] => 2
[data] => 300
)
[http://yandex.com] => Array (
[position] => 3
[data] => 5513
)
)
Is this achievable in Mongo?
The reordering of fields issue has been fixed as of MongoDB v2.5.2 (2.6 release). Having said that one way you can avoid the issue completely is having results as an array instead of a (sub)document. Also note you should not use "." as part of the key name either.
With 2.4, with the following you will see there is reodering in the case of _id=1 (subdocument) but not in the case of _id=2 (array).
$document = array("_id" => 1, "results" => array('http://google.com' => array('position' => 1, 'data' => 42672),
'http://bing.com' => array('position' => 2, 'data' => 9423),
'http://yandex.com' => array('position' => 3, 'data' => 5513)));
$coll->insert($document);
$document = array("_id" => 2, "results" => array(array('site' => 'http://google.com', 'data' => 42672),
array('site' => 'http://bing.com', 'data' => 9423),
array('site' => 'http://yandex.com', 'data' => 5513)));
$coll->insert($document);
$coll->update(array("_id" => 1), array('$set'=>array("results.http://bing.com.data"=>300)));
$coll->update(array("_id" => 2, 'results.site' => 'http://bing.com'), array('$set'=>array('results.$.data'=>300)));
I've included examples below using the mongo shell for clarity, but the PHP equivalent should be straightforward to work out.
I notice you originally modelled your list of sites as an embedded document, however the order of fields within an embedded document is currently not guaranteed to be preserved so you should instead use an array.
Additionally, you cannot use field names with embedded dots (.) in MongoDB so you should not plan to store urls as field names (see: Field name restrictions).
In order to find an element in an array you need to search by a value (not a field name) so your schema should look more like:
{
_id: ObjectId("52a46b44aabacb5c218b4567"),
results: [
{
site: 'http://google.com',
position: 1,
data: 42762
},
{
site: 'http://bing.com',
position: 2,
data: 9423
},
{
site: 'http://yandex.com',
position: 3,
data: 5513
}
]
}
Assuming the array site elements are unique, you can use the positional operator $ to find and update the matching embedded document in place.
For example, to perform your update of the "bing.com" data value:
db.sites.update(
// Match criteria
{
_id:ObjectId("52a46b44aabacb5c218b4567"),
'results.site':'http://bing.com'
},
// Update
{ $set: {
'results.$.data': 300 }
}
)
In MongoDB 2.4+ you have the option of pushing to a sorted array which could also be a useful approach to maintaining your array in sorted order when you add new entries.
It's worth noting that if you plan to store many (i.e. thousands) of items in an array this can impose a significant performance penalty due to document growth and the complexity of updating large arrays.
I am pretty sure that (as every other DBMS) you can't and should't rely on records orders.
Instead I would advice you to add index (on position, i.e. db.people.ensureIndex( { position: 1 } )) and query your record sorted by that field, i. e.: db.collection.find().sort( { position: 1 } )

Querying array elements with Mongo

How can I query the smoothies that have apple in them? (below is a collection with 3 documents)
_id => 1
name => 'best smoothie'
ingredients => Array
(
[0] => apple
[1] => raspberry
[2] => orange
[3] => banana
)
_id => 2
name => 'summer smoothie'
ingredients => Array
(
[0] => lemon
[1] => mint
)
_id => 3
name => 'yogurt smoothie'
ingredients => Array
(
[0] => apple
[1] => blueberry
)
If you simply run the below query MongoDB is smart enough to figure out what you're trying to do.
{ ingredients: "apple" }
Mongo will see that ingredients is a list and only return documents that contain "apple" some where in that list.
From the documentation:
Note: Fields containing arrays match conditional operators, if only one
item matches.
Therefore, the following query:
db.collection.find( { field: { $gt:0, $lt:2 } } );
Will match a document that contains the
following field:
{ field: [-1,3] }
Why do people write scalable applications for smoothies?
db.find({"ingredients":{$in: "apple"}});