ReferenceOne with MongoDB - mongodb

I've got a problem with Symfony2.0 BETA3 and MongoDB. I want create a Document, where a Field References to another Class, this might look like this:
namespace test\TestBundle\Document;
use test\TestBundle\Document\Location;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
/**
* #ODM\Document(collection="locationcache", repositoryClass="test\TestBundle\Document\LocationCacheRepository")
*/
class LocationCache
{
// many more fields...
/**
* #var Location
* #ODM\ReferenceOne(targetDocument="test\TestBundle\Document\Location")
*/
protected $location;
/**
* #param Location
*/
public function setLocation(Location $location)
{
$this->location = $location;
}
/**
* #return Location
*/
public function getLocation()
{
return $this->location;
}
}
But if I want to find a location by $id like this
class LocationCacheRepository extends DocumentRepository
{
public function findByLocationID(MongoId $locationID)
{
return $this->createQueryBuilder()
->field('location.$id')->equals($locationID)
->sort('year', 'asc')
->sort('month', 'asc')
->getQuery()
->execute();
}
}
I will get this error
No mapping found for field 'location' in class 'test\TestBundle\Document\LocationCache'.
UPDATE
Here is a Document
Array
(
[_id] => 4dd637e706936bbcc0ac012d
[days] => Array
(
[1] => Array
(
[money] => 9
)
[2] => Array
(
[money] => 21
)
[3] => Array
(
[money] => 38
)
[4] => Array
(
[money] => 6
)
[18] => Array
(
[money] => 6
)
[19] => Array
(
[money] => 3
)
[31] => Array
(
[money] => 11
)
)
[location] => Array
(
[$ref] => location
[$id] => 4dd554c91c911a6606000000
[$db] => test
)
[money] => 94
[month] => 1
[year] => 2011
)
I don't know what's the problem with the class. Could please someone help?
Thanks in advance!
Monty

If you want search on any location field you need to use 'embedOne' instead of 'referenceOne'.
ReferenceOne not copy location fields into parent document, it just data like this (i don't remember exactly):
{
refId: '1',
refColl: 'locations',
refDb: 'location_database'
}
But in general if you need query only by location id you just need take a look how location reference looks like in mongodb using mongoshell or some other tool.
So you query will be like this:
->field('location.$refId')->equals($locationID)

Related

yii2 mongodb - how to find element in collection subarray

Array from collection looks like this.
$result = $collection->find();
Array
(
[0] => Array
(
[_id] => MongoDB\BSON\ObjectId Object
(
[oid] => 5c52b90454851c44aa2987e2
)
[name] => Array
(
[date] => 2019-01-31 10:59:48
[value] => DESKTOP-TODTF5E
)
[network_addresses] => Array
(
[0] => Array
(
[ip_1] => 12.21.134
[ip_2] => 50
[mac] => xx:xx:xx:xx:xx:xx
)
[1] => Array
(
[ip_1] => 192.168.0
[ip_2] => 2
[mac] => yy:yy:yy:yy:yy:yy
)
)
)
)
I can find if some mac exist in specific row of sub array like this:
$result = $collection->find(["network_addresses.0.mac" =>
"xx:xx:xx:xx:xx:xx"]);
But I need to check if certain mac exists in any row of subarray, so instead of row index 0 I need to put some asterix or something.
How to do that ?
$query = (new Query)->select(["name"])
->from(['db_name','collection_name'])
->where(["network_addresses" => [ '$elemMatch' =>['mac' => "xx:xx:xx:xx:xx:xx"]]]);
$results = $query->all();

Query an entity in a different Language

I'm trying to query entietes in a language, other than the system default one, my repository method looks like this,
public function findOneByMaterialnumber( $materialnumber, $sysLanguageUid ){
$query = $this->createQuery();
$query->matching($query->like('materialnumber',$materialnumber));
$query->getQuerySettings()->setIgnoreEnableFields(true);
$query->getQuerySettings()->setRespectStoragePage(false);
$query->getQuerySettings()->setLanguageUid($sysLanguageUid);
//$query->getQuerySettings()->setRespectSysLanguage(false);
//$query->getQuerySettings()->setLanguageMode('strict');
//$query->getQuerySettings()->setLanguageOverlayMode(false);
$parser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbQueryParser');
$queryParts = $parser->parseQuery($query);
//\TYPO3\CMS\Core\Utility\DebugUtility::debug($queryParts, 'Query');
print_r($queryParts);
exit;
return $query->execute()->getFirst();
}
but the query this results in still incorporates the sys_language_uid in the non-strict way. The debugged query object looks like this.
[keywords] => Array
(
)
[tables] => Array
(
[tx_productfinder_domain_model_product] => tx_productfinder_domain_model_product
)
[unions] => Array
(
)
[fields] => Array
(
[tx_productfinder_domain_model_product] => tx_productfinder_domain_model_product.*
)
[where] => Array
(
[0] => tx_productfinder_domain_model_product.materialnumber LIKE :
)
[additionalWhereClause] => Array
(
[0] => (tx_productfinder_domain_model_product.sys_language_uid IN (0,-1))
)
[orderings] => Array
(
[0] => tx_productfinder_domain_model_product.ordercode ASC
[1] => tx_productfinder_domain_model_product.title ASC
[2] => tx_productfinder_domain_model_product.materialnumber ASC
)
[limit] =>
[offset] =>
[tableAliasMap] => Array
(
[tx_productfinder_domain_model_product] => tx_productfinder_domain_model_product
)
This happens regardless of the sys_language_uid i query for. What am I doing wrong?
As you can see, I've tried combinations of all sorts of QuerySettings, setRespectSysLanguage, setLanguageMode and setLanguageOverlayMode. As I understand it, I have to query strictly and without language overlay. But none of those, nor their combinations, worked as intended.
This works with TYPO3 8.7.xx
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
/**
* The repository for Products
*/
class ProductRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
{
/*
* #param int $uid id of record
* #param int $langUid sys_language_uid of the record
* #return \ITSHofmann\ItsProductfile\Domain\Mpdell\Product
*/
public function findByUidAndLanguageUid($uid,$langUid)
{
$query = $this->createQuery();
$object = $query->matching(
$query->equals('uid', $uid)
)->execute()->getFirst();
if ($object) {
$className = get_class ($object);
$dataMapper = $this->objectManager->get(DataMapper::class);
$tableName = $dataMapper->getDataMap($className)->getTableName();
$transOrigPointerField = $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'];
$languageField = $GLOBALS['TCA'][$tableName]['ctrl']['languageField'];
$connection = GeneralUtility::makeInstance(ConnectionPool::class);
$queryBuilder = $connection->getQueryBuilderForTable($tableName );
$statement = $queryBuilder->select('*')
->from($tableName )
->where(
$queryBuilder->expr()->eq(
$transOrigPointerField,$queryBuilder->createNamedParameter($object->getUid(), \PDO::PARAM_INT)),
$queryBuilder->expr()->eq(
$languageField,$queryBuilder->createNamedParameter($langUid, \PDO::PARAM_INT))
)->execute();
$objectRow = $statement ->fetch();
if ($objectRow) {
$langObject = $dataMapper->map($className,[$objectRow]);
if ($langObject ) {
return reset ($langObject );
}
}
}
return $object;
}
}
edit. The answer I posted here originally turned out not to work either. What I ended up doing instead, was to write a custom statement, execute it to return the raw data and map it, via DataMapper->map(); Refer to Christop Hofmanns answer for details.

Using FAL in Extbase correctly

Domain model
class Image extends AbstractContent {
/**
* #var \TYPO3\CMS\Extbase\Domain\Model\FileReference
*/
protected $file;
/**
* Gets the image file
*
* #return \TYPO3\CMS\Extbase\Domain\Model\FileReference
*/
public function getFile() {
return $this->file;
}
/**
* Sets the image file
*
* #param \TYPO3\CMS\Extbase\Domain\Model\FileReference $file
* #return void
*/
public function setFile($file) {
$this->file = $file;
}
}
Import service fragments
/**
* #var \TYPO3\CMS\Core\Resource\ResourceStorage
*/
protected $defaultStorage;
[...]
$this->defaultStorage = ResourceFactory::getInstance()->getDefaultStorage();
[...]
$file = $this->defaultStorage->addFile(
'/tmp/4711',
$this->defaultStorage->getRootLevelFolder(),
'foo.jpg',
'overrideExistingFile'
);
$falReference = ResourceFactory::getInstance()->createFileReferenceObject(
array(
'uid_local' => $file->getUid(),
'uid_foreign' => uniqid('NEW_'),
'uid' => uniqid('NEW_'),
)
);
$reference = GeneralUtility::makeInstance(FileReference::class);
$reference->setOriginalResource($falReference);
$content = GeneralUtility::makeInstance(Image::class);
$content->setFile($reference);
After saving $content the image is available through the record and the filemount but the Ref column in BE > FILE > File List) is - and not >= 1. So its look like the reference is some how broken. When I'm using the BE to add an image to the record it's all fine. I'm using TYPO3 CMS 7.3-dev.
What's wrong with my code?
I get the hint in the Slack channel of TYPO3.
You just need to set plugin.tx_myext.persistence.updateReferenceIndex = 1 respectively module.tx_myext.persistence.updateReferenceIndex = 1 and the index will be updated.
Alternatively you could use \TYPO3\CMS\Core\Database\ReferenceIndex::updateRefIndexTable().
When I had to use FAL in my extension I found this link:
http://t3-developer.com/extbase-fluid/extensions-erweitern/fal-in-eigenen-extensions/fal-in-typo3-extensions-verwenden/
Since it is in German, I will in the very shortest explain what is done there:
extend your data model in ext_tables.sql
add a column of some char type (e.g. varchar)
add your column to the column section in your TCA array in ext_tables.php
'mypictures' => array(
'exclude' => 1,
'label' => 'My Pictures',
'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig('image', array(
'appearance' => array(
'createNewRelationLinkTitle' => 'LLL:EXT:cms/locallang_ttc.xlf:images.addFileReference'
),
'minitems' => 0,
'maxitems' => 99,
), $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']),
),
Extend your modelfiles. Pay attention to annotations!
You can use your media in your fluid template

In CakePHP am getting this error: "Fixture invalid: Count of fields does not match count of values"

When I am running test cases I am getting the above error: "Fixture invalid: Count of fields does not match count of values".
Can anyone say why I would be getting that? And how to fix it?
I must note that for my fixtures, I am automatically importing the table definition like so:
/**
* Import table definition
*
* #var string
*/
public $import = 'Category';
/**
* Records
*
* #var array
*/
public $records = array(
array(
'id' => 1,
'name' => 'Science',
'post_count' => 0
),
array(
'id' => 2,
'name' => 'Information Technology',
'post_count' => 0
),
array(
'id' => 3,
'name' => 'Philosophy',
'post_count' => 0
)
);
I am using CakePHP 2.5, xampp.
Ah, the error was explicit. I was importing the table definition for the model automatically, but had the wrong list of fields in the records section.

SugarCRM: how to get all contacts for an account via REST API

I am trying to get all contacts for a particular account (i know the account id) from SugarCRM using the v2 REST API.
I am sending a GET request with the following parameters:
input_type => 'JSON'
response_type => 'JSON'
method => 'get_entry_list'
rest_data => '{session:"some-valid-session-id", module_name:"Contacts", query:"contacts.account_id=some-valid-id"}'
I expect to get all contacts that are related to this accoutn, but instead I get an error "... MySQL error 1054: Unknown column 'contacts.account_id' in 'where clause'"
However, when I try to get all contacts without providing any query (query='') I get all the contacts with all their properties and I can see that there is an account_id property.
Can anyone help?
Try query:"accounts.id=some-valid-id".
It has worked for me in the past with the SOAP API.
Here's my method. It uses this wrapper class: http://github.com/asakusuma/SugarCRM-REST-API-Wrapper-Class/
/**
* returns an array of contacts that are related to the accountId passed as a param.
* The array returned will be an array of associative arrays.
* #param $accountId
* #param array $contactSelectFields optional sets the different items to return, default includes id, email1, name, title, phone_work, and description
* #return array
*
*/
public function getAllContactsAtOrganization( $accountId, $contactSelectFields=array("id", "email1", "name", "title", "phone_work", "description")) {
$sugar = new Sugar_REST( SUGAR_REST_URL, SUGAR_USER_NAME, SUGAR_PASSWORD);
$fields = array( "Accounts" => array("id", "name"),
"Contacts" => $contactSelectFields);
$options = array(
'where' => "accounts.id='$accountId'"
);
$apiResult = $sugar->get_with_related("Accounts", $fields, $options );
$contacts = array();
foreach( $apiResult['relationship_list'][0]['link_list'][0]['records'] as $almostContact) {
$curr = array();
foreach($contactSelectFields as $key) {
$curr[$key] = $almostContact['link_value'][$key]['value'];
}
$contacts[] = $curr;
}
//print_r($contacts);
return $contacts;
}
Sample Return
Array
(
[0] => Array
(
[id] => 47e1376c-3029-fc42-5ae2-51aeead1041b
[email1] => johndoe#gmail.com
[name] => Blake Robertson
[title] => CTO
[phone_work] => 8881112222
[description] => Opinionated developer that hates SugarCRM's REST API with a passion!
)
[1] => Array
(
[id] => 4c8e3fcf-8e69-ed7d-e239-51a8efa4f530
[email1] => csmith#mailinator.com
[name] => Carolyn Smith
[title] => Director of Something
[phone_work] => 832-211-2222
[description] => She's a smooth operator...
)
)
For Reference Purposes
Here's the "rest-data" (nicely formatted)
Used print_r of the php array
Array
(
[session] => 9j7fm4268l0aqm25kvf9v567t3
[module_name] => Accounts
[query] => accounts.id='e583715b-7168-5d61-5fb1-513510b39705'
[order_by] =>
[offset] => 0
[select_fields] => Array
(
[0] => id
[1] => name
)
[link_name_to_fields_array] => Array
(
[0] => Array
(
[name] => contacts
[value] => Array
(
[0] => id
[1] => email1
[2] => name
[3] => title
[4] => phone_work
[5] => description
)
)
)
[max_results] => 20
[deleted] => FALSE
)
Post Body
method=get_entry_list&input_type=JSON&response_type=JSON&rest_data={"session":"iov5a257lk5acsg9l3ll6kuej3","module_name":"Accounts","query":"accounts.id='e583715b-7168-5d61-5fb1-513510b39705'","order_by":null,"offset":0,"select_fields":["id","name"],"link_name_to_fields_array":[{"name":"contacts","value":["id","email1","name","title","phone_work","description"]}],"max_results":20,"deleted":"FALSE"}method=logout&input_type=JSON&response_type=JSON&rest_data={"session":"iov5a257lk5acsg9l3ll6kuej3"}
I'm not familiar with SugarCRM yet, but did you try with just account_id=some-valid-id ? because I also did a REST request to add a contact to sugarcrm and I didn't mention the table's name, just the fields. I didn't try this but it seems logical to me since you already mentionned the module's name, so I guess sugar kind of knows what table(s?) to look for when processing your query.