CosmosDB's index recommendations that include arrays seem to be in an unsupported format (w/ PopulateIndexMetrics) - azure-cosmosdb

I'm using CosmosDB's V3 API. I set PopulateIndexMetrics to true to generate index recommendations. However, some of the recommendations (relating to arrays) seem to be in an unsupported format and when I try and add them as is (to my containers' indexes) the operation fails.
Here is an example composite index recommendation which I get when I set PopulateIndexMetrics to true (where a and c are simple string properties and b is an array of strings):
Index Spec: "/a ASC, /b/[] ASC, /c ASC\r\n"
However, this array format isn't supported when I try and add this composite index via the Azure Portal. And I've already added this to the index: "/a ASC, /b ASC, /c ASC" (I removed the square parantheses) yet when I rerun the index recommender it still re-recommends the missing index with the unsupported format.
Any help would be appreciated.
Thanks!

I'm unsure why PopulateIndexMetrics would make such a suggestion, but a composite index can only include scalar values.
Composite paths lead to a scalar value that is the only value included in the composite index.
As found in the Microsoft Docs

Related

How to get duplicates in Alfresco?

I have a task: "to get a duplicates (documents with same property value) from Alfresco database with count duplicates amounts".
In MySql there will be something like that:
mysql> SELECT COUNT(*) AS repetitions, last_name, first_name
-> FROM cat_mailing
-> GROUP BY last_name, first_name
-> HAVING repetitions > 1
But I have read that "The CMIS query language in Alfresco does not support GROUP BY or HAVING." . Is there any query (in any supported language) to perform described task?
Thank you!
UPD: for now I am counting in JVM this way (redefining hashCode/equals for Form20Row)
Map<Form20Row, Form20Row> rowsMap = results.stream().parallel().map(doc -> {
Form20Row row = new Form20Row();
String propMark = propertyHelper.getNodeProp(doc, NDBaseDocumentModel.PROP_MARK);
row.setGroupName(systemMessages.getString("form20.nss.name"));
row.setDocMark(propMark);
row.setDupesNumber(1);
return row;
}).collect(Collectors.toConcurrentMap(form20Row -> form20Row, form20Row -> form20Row,
(existing, replacement) -> {
int count = existing.getDupesNumber();
existing.setDupesNumber(++count);
return existing;
}));
Alfresco uses SOLR for search on nodes but SOLR is very limited on joins, aggregate functions, counting ... What you may do is querying the SOLR index using facets like facet.field=field1&facet.mincount=1.
Personally I would prefer to query the alfresco db directly to find nodes having the same property values for specific properties. This will not depend on the solr index and gives you the full flexibility of SQL.
I agree with Heiko.
This won't be trivial either, since Alfresco keeps "everything" in "alf_node_properties" table, and in case of strings in "string_value" column. So you can't know "which" property this is without joining with "alf_qname" table, and for larger databases this can take a longish time.
You probably want to filter out deleted and node versions, and not compare them at all.

Cosmos db Order by on 'computed field'

I am trying to select data based on a status which is a string. What I want is that status 'draft' comes first, so I tried this:
SELECT *
FROM c
ORDER BY c.status = "draft" ? 0:1
I get an error:
Unsupported ORDER BY clause. ORDER BY item expression could not be mapped to a document path
I checked Microsoft site and I see this:
The ORDER BY clause requires that the indexing policy include an index for the fields being sorted. The Azure Cosmos DB query runtime supports sorting against a property name and not against computed properties.
Which I guess makes what I want to do impossible with queries... How could I achieve this? Using a stored procedure?
Edit:
About stored procedure: actually, I am just thinking about this, that would mean, I need to retrieve all data before ordering, that would be bad as I take max 100 value from my database... IS there any way I can do it so I don t have to retrieve all data first? Thanks
Thanks!
ORDER BY item expression could not be mapped to a document path.
Basically, we are told we can only sort with properties of document, not derived values. c.status = "draft" ? 0:1 is derived value.
My idea:
Two parts of query sql: The first one select c.* from c where c.status ='draft',second one select c.* from c where c.status <> 'draft' order by c.status. Finally, combine them.
Or you could try to use stored procedure you mentioned in your question to process the data from the result of select * from c order by c.status. Put draft data in front of others by if-else condition.

Is this normal behavior for a unique index in Sqlite?

I'm working with SQLite in Flash.
I have this unique index:
CREATE UNIQUE INDEX songsIndex ON songs ( DiscID, Artist, Title )
I have a parametised recursive function set up to insert any new rows (single or multiple).
It works fine if I try to insert a row with the same DiscID, Artist and Title as an existing row - ie it ignores inserting the existing row, and tells me that 0 out of 1 records were updated - GOOD.
However, if, for example the DiscId is blank, but the artist and title are not, a new record is created when there is already one with a blank DiscId and the same artist and title - BAD.
I traced out the disc id prior to the insert, and Flash is telling me it's undefined. So I've coded it to set anything undefined to "" (an empty string) to make sure it's truly an empty string being inserted - but subsequent inserts still ignore the unique index and add a brand new row even though the same row exists.
What am I misunderstanding?
Thanks for your time and help.
SQLite allows NULLable fields to participate in UNIQUE indexes. If you have such an index, and if you add records such that two of the three columns have identical values and the other column is NULL in both records, SQLite will allow that, matching the behavior you're seeing.
Therefore the most likely explanation is that despite your effort to INSERT zero-length strings, you're actually still INSERTing NULLs.
Also, unless you've explicitly included OR IGNORE in your INSERT statements, the expected behavior of SQLite is to throw an error when you attempt to insert a duplicate INDEX value into a UNIQUE INDEX. Since you're not seeing that behavior, I'm guessing that Flash provides some kind of wrapper around SQLite that's hiding the true behavior from you (and could also be translating empty strings to NULL).
Larry's answer is great. To anyone having the same problem here's the SQLite docs citation explaining that in this case all NULLs are treated as different values:
For the purposes of unique indices, all NULL values are considered
different from all other NULL values and are thus unique. This is one
of the two possible interpretations of the SQL-92 standard (the
language in the standard is ambiguous). The interpretation used by
SQLite is the same and is the interpretation followed by PostgreSQL,
MySQL, Firebird, and Oracle. Informix and Microsoft SQL Server follow
the other interpretation of the standard, which is that all NULL
values are equal to one another.
See here: https://www.sqlite.org/lang_createindex.html

Why are some SQLite functions zero-based and some one-based

The index parameter for sqlite3_column_* is zero-based while sqlite3_bind_* is one-based.
Is there a reason for this?
I've got it.
Blame sqlite3_bind_parameter_index:
Return the index of an SQL parameter given its name. The index value returned is suitable for use as the second parameter to sqlite3_bind(). A zero is returned if no matching parameter is found.
So there you go. Odd choice, considering they seem to be using a signed int for the index, meaning they could have used -1 to indicate a no-match. Maybe the reason behind that is more historical, SQLite has been around for a while...

BizTalk Database Lookup functoid fixed condition

Is there a way to further restrict the lookup performed by a database lookup functoid to include another column?
I have a table containing four columns.
Id (identity not important for this)
MapId int
Ident1 varchar
Ident2 varchar
I'm trying to get Ident2 for a match on Ident1 but wish it to only lookup where MapId = 1.
The functoid only allows the four inputs any ideas?
UPDATE
It appears there is a technique if you are interested in searching across columns that are string data types. For those interested I found this out here...
Google Books: BizTalk 2006 Recipes
Seeing as I wish to restrict on a numberic column this doesn't work for me. If anyone has any ideas I'd appreciate it. Otherwwise I may need to think about my MapId column becoming a string.
I changed the MapId to MapCode of type char(3) and used the technique described in the book I linked to in the update to the original question.
The only issue I faced was that my column collations where not in line so I was getting an error from the SQL when they where concatenated in the statement generated by the map.
exec sp_executesql N'SELECT * FROM IdentMap WHERE MapCode+Ident1= #P1',N'#P1 nvarchar(17)',N'<MapCode><Ident2>'
Sniffed this using the SQL Profiler

Resources