I have a collection in mongo which has array field. When I query that collection I want to return documents whose elements in the array field represent a subset of the array I'm comparing with. So all array elements in the document that satisfies the condition should also be present in the array I'm comparing with but that array can have additional elements.
In this case document with ArrayField satisfies condition
'ArrayField' =>
array (
'KeyA' => 'ValueA',
'KeyB' => 'ValueB',
'KeyC' => 'ValueC'
)
'ComparedArray' =>
array (
'KeyA' => 'ValueA',
'KeyB' => 'ValueB',
'KeyC' => 'ValueC',
'KeyD' => 'ValueD',
)
In this case document does not satisfy the condition
'ArrayField' =>
array (
'KeyA' => 'ValueA',
'KeyB' => 'ValueB',
'KeyC' => 'ValueC'
)
'ComparedArray' =>
array (
'KeyA' => 'ValueA',
'KeyB' => 'ValueB',
)
I'm really stuck and can't find a way how to write this query. Any suggestions?
The documents we want can be obtained by:
Checking for documents where the arrayField does not have an element,
that is not present in the comparedArray.
use $elemMatch and $nin operators to find at least one element that is present in arrayField but not in comparedArray.
Apply a negative condition using $not operrator, to the above to get the documents that we want.
Code:
db.collection.find({"arrayField":
{$not:
{$elemMatch:
{$nin:comparedArray}}}})
PHP:
$notIn= array('$nin'=>comparedArray);
$eleMatch= array('$elemMatch' => $notIn);
$not = array('$not' => $eleMatch);
$collection -> find(array("arrayField" => $not);
Related
from request I get an array like this:
'array' => [
0 => ['id' => 1,'val' => 2],
1 => ['id' => 1,'val' => 2]
]
I need to validate it so all ids of array will be unique.
right now I try this validation rule:
'array.*.id' => 'different:array.*.id'
but it will check current array with current array so result will be like
The array.0.id and array.0.id must be different.
You should use distinct rule:
'array.*.id' => 'distinct'
I'm using Google Analytics API to populate a dashboard. I'm curious if there is a setting I am unaware of that can return the rows as follows:
[0] => Array
(
[ga:pagePath] => /
[ga:pageViews] => 856
)
Instead of just 0, 1, .etc. numerical arrays:
[columnHeaders] => Array
(
[0] => Array
(
[name] => ga:pagePath
[columnType] => DIMENSION
[dataType] => STRING
)
[1] => Array
(
[name] => ga:pageViews
[columnType] => METRIC
[dataType] => INTEGER
)
)
[totalsForAllResults] => Array
(
[ga:pageViews] => 2099
)
[rows] => Array
(
[0] => Array
(
[0] => /
[1] => 856
)
[1] => Array
(
[0] => /portfolio
[1] => 268
)
I know how to do this with array logic but was just curious if there was a setting or something I could query GA with to get the first format. Couldn't find any info elsewhere.
No there isn't, neither in v3 nor in v4 (it would be terribly inefficient to repeat the dimension names for each row).
What you can do is define the index of dimensions & metrics so you can refer to values by name instead of index (below example in JavScript):
var ga = {
pagePath: 0,
pageView: 1
}
rows[1][ga.pagePath]; // /portfolio
rows[2][ga.pageViews]; // 268
I have this array from a sql query :
[0] => Array
(
[T1] => Array
(
[First] => A
[Second] => Apples
[LastChild] => F
)
[0] => Array
(
[LastChildNb] => 23
)
)
I would like to have this result :
[0] => Array
(
[0] => Array
(
[First] => A
[Second] => Apples
[LastChild] => F
[LastChildNb] => 23
)
)
How do I do this ? I think I should use "hash::combine", but what would the code be ?
You could do something like this, with $arr being your array above:
$arr = array_reduce($arr, function(&$arr, $v) {
return array_merge($arr, (array) $v);
}, array());
You can do
array_merge($arr[0]['T1'], $arr[0][0])
Where $arr is defined as follows:
$arr = [0 => Array
(
'T1' => Array
(
'First' => 'A',
'Second' => 'Apples',
'LastChild' => 'F'
),
0 => Array
(
'LastChildNb' => 23
)
)];
For multiple records in $arr, you can simply cycle over all records and do this merge manually.
However, assuming you're getting the array as a result of a find() method, I suggest you consider using T1__LastChildNb as an alias within the 'fields' of your condition. Simply said, if you have a find like following:
$this->T1->find('all', ['fields' => 'T1.*, (SOME SUBQUERY) AS LastChildNb']);
then modifying it to be
$this->T1->find('all', ['fields' => 'T1.*, (SOME SUBQUERY) AS T1__LastChildNb']);
might be what you're looking for since it will return desired array directly (tested on 2.6).
Let me know if you're interested in more information.
When I use this code,
$views = array();
$views[]=['somevalue'=>'customerview.php'];
$views[]=['anothervalue'=>'ordersview.php'];
I get this,
Array
(
[0] => Array
(
[somevalue] => customerview.php
)
[1] => Array
(
[anothervalue] => ordersview.php
)
)
How can I make it get rid of the initial array without using array_shift or the like? Why is it putting the numerical array in the first place instead of just this,
Array
(
[somevalue] => customerview.php
[anothervalue] => ordersview.php
)
EDIT: How can I use the short syntax for this? Is that possible?
When you do this:
$views[] = ['somevalue' => 'customerview.php'];
you're saying, "Push another element onto the array, and assign to it the following value:
'somevalue' => 'customerview.php'
But this quantity is an array key and an array value. So what you're doing is inserting into your $views array a single element that itself contains an array key and array value. This explains the behavior you're seeing.
This should give you the results you want:
$views = array();
$views['somevalue'] = 'customerview.php';
$views['anothervalue'] ='ordersview.php';
Or, in shorthand:
$views = [
'somevalue' => 'customerview.php',
'anothervalue' => 'ordersview.php'
];
or you can do:
$value1 = 'first';
$value2 = 'second';
$array = array(
$value1 => 'customerview.php',
$value2 => 'ordersview.php'
);
$views is already an array so when you use $views[], you are adding another array into the existing array.
You need to use
$views = array(
'somevalue' => 'customerview.php',
'anothervalue' => 'ordersview.php'
)
The Set::extract is a very powerful function to filter out data retrieved from find method.
However, as far as I know, the results are not nested. I mean, if I have an array like
data =
Array (
0 => array(
'User' => Array (...),
'Profile => Array (...)
)
1 => array(
'User' => Array (...),
'Profile => Array (...)
)
)
and I would extract all User with, let's say, User.type =1, I would do:
$filtered Set::extract('/User[type=1',$data).
$filtered = Array(
0 => Array (
'User' => Array()
)
)
and the other array, Profile, is not shown. Is it possible to get all the data when filtering with extract?
You can traverse back the array path with /../ inside the first parameter.
Try
$filtered = Set::extract('/User[type=1]/..',$data);
Source: http://book.cakephp.org/2.0/en/core-utility-libraries/set.html#Set::extract
It says it's basic XPath 2.0 syntax and one of the examples uses it.