Tridion Query for component that have no exact metadata field - tridion

I have a components that based on schema that have a non mandatory metadata field ExtendedType. I can query for a component that have this field with a certain value:
new CustomMetaValueCriteria(new CustomMetaKeyCriteria("ExtendedType"), "Highlight", Criteria.Equal)))
I need to query for a components that have no this field filled in. How can I query for a that.
In SQL I can write next:
select * from t where t.ExtendedType IS NULL
How can i do this using Trdion Query? In common i need to implement query like:
select * from t where t.ExtendedType = "Highlight" OR t.ExtendedType IS NULL

You might be able to achieve this with the NotInCriteria, as follows:
new NotInCriteria
(
new CustomMetaValueCriteria
(
new CustomMetaKeyCriteria("ExtendedType"), "%", Criteria.Like
)
)
I haven't tested this, it's just a thought. Even if it works, be sure to check if it performs as well!
PS: next time, please use the tridion.stackexchange.com forum for Tridion-related questions!

Related

Create item if not found and return old one if existing in dynamodb, in one call

In DynamoDb, is it possible to do a conditional put and return the old item if there already was a matching item?
I would like something like the following to create the row if the user does not already exist, and if it does exist, I want it to return the old item (with whatever name was there before). I.e., insert item if new, else just read existing item.
await documentClient.put({
TableName: 'table',
Item: {
userId: 'user0',
name: 'smith',
},
ConditionExpression: 'attribute_not_exists(userId)',
});
Is this possible to do in one call?
Sort of.
If you use UpdateItem it will create or update the item. It only updates the fields that have changed however, so if your fields have not changed, then no update will be made. It will also create the item if you do not have it.
Using Conditional Items for this will return an ErrorCode if the condition fails ConditionalCheckFailedException - which would require an additional operation.
(I don't use the javascript SDK that much, more in python, so I'm not sure this is the correct version/page but here is some documentation:
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB.html#updateItem-property )

How to filter objects based on the Symfony workflow's place which is an array?

I've been struggling with this for a while but can't find a clean way to do it, so I'm seeking for some help.
I have custom filters (ApiPlatform 2.5 and Symfony 5.1) on database API outputs, and I need to filter on the current workflow place, or status as you like, of each output.
The Status has the below structure, which is a symfony workflow's place :
Status = { "OPEN": 1 }
My issue is that the status is stored as an array in the DB, and I can't find a way to have the querybuilder finding a match.
I've tried to build locally an array to do an = , a LIKE or an IN :
$status['OPEN'] = 1;
$queryBuilder->andWhere(sprintf('%s.Status = :st', $rootAlias))
->leftJoin(sprintf('%s.Objs', $rootAlias), 'o')
->andWhere('o.Profile = :p')
->setParameters(array(
'st' => $status,
'p' => $profile
));
But no way :(
I implemented a workaround that works but I don't like it as I'm using workflows a lot and need a clean way to filter outputs.
My workaround is fairly simple, when the status is writen as an array in the DB, I also store it as a string in another field called StatusText, then filtering on StatusText is easy and straight.
Status can have different contents obviously : OPEN, CLOSING, CLOSED, ...
Help appreciated !!
Thanks
EDIT & Solution
As proposed by Youssef, use scienta/doctrine-json-functions and use JSON_EXTRACT :
composer require scienta/doctrine-json-functions
Important, that was part of my issue, use the Doctrine type json_array an not array to store the status or the state, however you call it, in the Database.
Integrate the alias provided inside the ApiPlatform custom filter :
$rootAlias = $queryBuilder->getRootAliases()[0];
$json_extract_string = "JSON_EXTRACT(".$rootAlias.".Status, '$.OPEN') = 1";
$queryBuilder->andwhere($json_extract_string )
->leftJoin(sprintf('%s.Objs', $rootAlias), 'o')
->andWhere('o.Profile = :p')
->setParameter('p', $profile);
You need to ask Doctrine if the JSON array contains the status, but you can't do that with the QueryBuilder method.
When you hit the ORM limitations you can use a Native Query with ResultSetMapping. It allows you to write a pure SQL query using specific features of your DBMS but still get entity objects.
Or you can use scienta/doctrine-json-functions and use JSON_EXTRACT

Updating Cassandra Map Value through querybuilder

Cassandra support updating specific value in Collection by syntax
ALTER TABLE users ADD todo map<timestamp, text>
UPDATE users SET todo['2012-10-2 12:00'] = 'throw my precious into mount doom'
WHERE user_id = 'frodo';
http://www.datastax.com/documentation/cql/3.0/cql/cql_using/use_map_t.html
Did not see any example of using QueryBuilder to update specific row in Map. How it can be done?
I think you have several options.
1/ Build your own query based on the CQL one.
Example: Consider that you have a table named Interactions and in your schema a column of type named 'attributes'.
String update ="UPDATE demo.Interactions SET attributes=attributes + {'i':'j'} where id='ff';
SimpleStatement statement = new SimpleStatement(update);
session.execute(statement);
2/ Use Java API.
Java API is not that documented indeed.
Let's take an example
a- Create an update object using queryBuilder
Update update = QueryBuilder.update(keyspace, tableName);
b- Then populate with 'put' or 'putAll' functions. put/putAll will add/update content
update.with(QueryBuilder.putAll(key, map));
To remove a key, set the content of a key to null, like:
for (Object item : map.keySet()) {
update.with(
QueryBuilder.put(columName, item, null)
);
}
Then execute the query.
Following methods are available for different types:
LIST:
QueryBuilder.appendAll(...)
QueryBuilder.discardAll(...)
SET:
QueryBuilder.addAll(...)
QueryBuilder.removeAll(...)
MAP:
QueryBuilder.putAll(...)
QueryBuilder.put(...)
The list is not exhautive.
Have a look in QueryBuilder class if you do not find what you are looking for.
Best regards and best luck with Cassandra.

How to implement "And"-Condition in ydn db?

I need help in ydn db.
My issue is as follows: How can I fetch records by 2 conditions?
In sql it would be:
"SELECT * FROM store WHERE name='Test' AND cool=1;"
Currently my attempt looks like this:
var keyRange = ydn.db.KeyRange.bound(['Test', true]);
var db = DB.getDatabase();
database
.get('personStore', 'name, cool', keyRange)
.done(function(records) {
console.log(records);
});
Thanks in advance :-)
As discussed in this page, you can use compound index (as you did) or key joining. If you index ['name', 'cool'], you should be able to query by ydn.db.KeyRange.only(['Test', 1]). Note that boolean is not a valid key. Even if cool is boolean value, you have to index as integer value. But my suggestion is index only name and, just query name and filter out cool value on the result set.

Self Referencing Table LINQ

Hello I have a table that has an "id" field and a "parentid" field. Both fields are required so you can't insert null into a parentid column to mark it as a "root" to the hierarchy. I'm having an issue with linq where when I create a new "root" I have to put in a dummy parentid until I know the id of the new root, then I have to updated the parentid field with the correct id and save it again. This seems silly, but I haven't found a better way to accomplish this yet?
TableWithHeirachy xobj = new TableWithHeirachy();
xobj.property1 = "test";
db.TableWithHeirachy.InsertOnSubmit(xobj);
db.SubmitChanges();
xobj.parentid = xobj.id;
db.SubmitChanges();
This seems really bad. Please tell me there is a better way!
A SQL Statement won't know the future ID of the row it's about to insert, until the insert has completed.
So, either continue as you are now - or instead use special values to indicate root records (null, -1, etc).

Resources