Trouble with N1QL query and index in Couchbase - couchbase

I have a straightforward N1QL query:
"select xrefId, CLSTR, CLUSTER_NAME, SHORTENED_NAME, "
+ "PRMRY, SET_NUM, TYPE from myBucket "
+ "where _class=\"com.package.model.ClusterCodeXref\"
And a corresponding secondary index (I'm not allowed to create a primary index on this bucket for internal reasons):
CREATE INDEX `idx_xref` ON `myBucket`(`xrefId`,`CLSTR`,`CLUSTER_NAME`,
`SHORTENED_NAME`,`PRMRY`,`SET_NUM`,`TYPE`)
where _class=`com.package.model.ClusterCodeXref` using GSI
Yet when I run the query (using spring-data-couchbase), I get the following error:
"No index available on keyspace myBucket that matches your query.
Use CREATE INDEX or CREATE PRIMARY INDEX to create an index, or check that your expected index is online."
Can someone explain what's wrong?

The leading index key and Index WHERE clause needs to be present in Query WHERE clause to choose the index.
The index where clause using back-ticks ( it means field in the document). Change those to double quotes and add _class as leading index key like below.
CREATE INDEX `idx_xref` ON `myBucket`(_class, `xrefId`,`CLSTR`,`CLUSTER_NAME`,
`SHORTENED_NAME`,`PRMRY`,`SET_NUM`,`TYPE`)
where _class="com.package.model.ClusterCodeXref" using GSI

Try with:
SELECT custom_data.xrefId, custom_data.CLSTR, custom_data.CLUSTER_NAME, custom_data.SHORTENED_NAME, custom_data.PRMRY, custom_data.SET_NUM, custom_data.TYPE
FROM `myBucket` AS custom_data
WHERE (`_class` = "com.package.model.ClusterCodeXref");
In String format:
"SELECT custom_data.xrefId, custom_data.CLSTR, "
+ "custom_data.CLUSTER_NAME, custom_data.SHORTENED_NAME, "
+ "custom_data.PRMRY, custom_data.SET_NUM, "
+ "custom_data.TYPE "
+ "FROM `myBucket` AS custom_data "
+ "WHERE (`_class` = \"com.package.model.ClusterCodeXref\");"

Related

How to query list of objects with paramteres that might not be entered?

I'm trying to query list of objects filtered by parameters that might not get entered by the user at all.
#Query(value = "SELECT * " +
"FROM project " +
"WHERE CASE WHEN (:location is not null) THEN location_Id LIKE :location" +
" and CASE WHEN (:category is not null) THEN category_Id LIKE :category", nativeQuery = true)
List<Project> getProjects(#Param("category") List<Category> category,
#Param("location") List<Location> location);
But i keep on getting similar errors that my syntax is wrong even tho i just copied it from a tutorial. Any idea where i might be mistaking?
If you want a single query:
WHERE (:location is null OR location_Id LIKE :location) AND
(:category is null OR category_Id LIKE :category)
From a performance perspective, OR can kill performance (by preventing the use of available indexes). Often applications build the WHERE clause for the non-NULL parameter values.

How to do data field update based on value in a another field inside the SQL statement

I have the following table where I used to manage passwords to login.
Loging Table fields :
UserID, EmailAddress, PassWord, LoginAttempts, LastLoginDate, LoginStatus
In my login logic,
1. If login password matches :
1. I update LastLoginDate field with the current date and time
2. Update LoginAttempts = 0
2. If the EmailAddress (login user name) is correct but PassWord is wrong :
1. I increment LogginAttempts by 1
2. If LoginAttempts > 5 then update LoginStatus = "LOCKED"
3. No need to update anything if EmailAddress is wrong
Currently I read the table with the following query :
string Query = #"SELECT *,GROUP_CONCAT(user_role.USER_ROLE_ROLE SEPARATOR ',') AS ROLES " +
"FROM login " +
"INNER JOIN user_role ON " +
"user_role.USER_ROLE_USER_ID = login.LOGIN_USER_ID AND login.LOGIN_EMAIL = #Parameter1";
Then I compare the fields for correct PassWord and update the table with following SQL query :
Query = #"UPDATE login SET " +
"LOGIN_ACCOUNT_STATUS = #Parameter2," +
"LOGIN_LOGIN_ATTEMPTS = #Parameter3," +
"LOGIN_LAST_LOGIN_DATE = #Parameter4," +
"LOGIN_LAST_LOGIN_LOCATION = #Parameter5 " +
"WHERE LOGIN_EMAIL=#Parameter1";
This is implemented externally (comparing values outside of SQL) and working fine. But I am sure this is possible to implement within SQL statement.
Could someone help me with the SQL query need to implement?
I want to see how I could merge SELECT and UPDATE into one SQL field with comparisons within SQL query if possible. I am just trying to make the code elegant. My C# function is currently 100 lines of code and could be reduced significantly if the whole thing is implemented in SQL.
Thanks,
PG

Best Way to form this query

Team,
I have three tables.
myTransTable,myMasterTable 1, MymyMasterTable 2
myTransTable have a lot of entries 'Rank.No ' auto incerement field is to identify indvidual records . 'U.Name' holds user name. Each user can have multiple records in this table . But the most recent transaction of a user can be find by the max value for Rank.No after grouping by 'U.Name'
Once this max record i.e recent transaction is fetched their asociated data needs to fetched from other tables
How can this be done in most efficent way.
1.myTransTable(fields Rank.No(auto increment field),Name,RecNum,uname,date,type)
2.myMasterTable1 (RecNum,Recowner,recdate)
3.MymyMasterTable2 (uName,age ,address,contact num)
I tried these ways for selection the max record and fetch the assocated data from other tables
max records as a view and fetch data from other tables using normal query
Max records and associated data itself as a view and select data as needed
Which is best way to have minimum execution time?
My queries are which is the best way to find the max.
Option one
select a.`RecNum`,a.`Name`,a.`Date`, a.`type`"+
"from myTransTable a "+
"INNER JOIN "+
"(SELECT RecNumMAX(`Rank.No`) AS maxserialnum FROM myTransTable "+
"GROUP BY RecNumMAX)groupedRecNumMAX "+
" ON "+
" a.RecNum = groupedPWO.RecNum "+
"AND "+
"a.`Rank.No` = groupedRecNumMAX.maxserialnum "+
Option two
Select a.`RecNum`,a.`Name`,a.`Date`, a.`type`"+`
FROM from myTransTable a
WHERE s.`RecNum` in(select MAX(`RecNum`)
from myTransTable
group by RecNum)
This is just a suggestion adn is related to your first query .. that seems contain wrong reference to table and column name
looking to you code you should use a query like this
select a.`RecNum`
,a.`Name`
,a.`Date`
, a.`type`
from myTransTable a
INNER JOIN (
SELECT RecNum, MAX(`Rank.No`) AS maxserialnum
FROM myTransTable
GROUP BY RecNum
) g ON a.RecNum =g.RecNum AND a.`Rank.No` = g..maxserialnum
and this with proper index .. on RecNum, and Rank.No should be the most performant (you can check in explain plain and with proper execution test)
You should not use column name with dot separated name as Rank.No .. use Rank_No isteand and also for column name the is preferred lowercase not and not a mix of UpperOrLower case use underscore for separate the word instead

"NOT IN" in HQL

I´m starting with Hibernate.
I have 2 tables in MySQL DB.
1)Unit
2)type: has as foreign key Unit_IdUnit
I have also in type a column name "Period" VARCHAR
I want to create this query on HQL:
SELECT *
FROM unit
WHERE IdUnit not in(SELECT Unit_IdUnit
FROM type
WHERE Period='2016-09');
If I run this query in Mysql it´s working. But I can´t make it works on HQL.
How could I create this query to return a list of Unit?
This is my first question, so please let me know if you need further information
You can use below HQL:
session.createQuery(
"from unit where IdUnit not in (SELECT Unit_IdUnit
FROM type
WHERE Period='2016-09')"
).list();
This is how I fix it.
Query query= session.createQuery("SELECT e1 FROM Unit e1 "
+ "WHERE e1.idUnit NOT IN ("
+ "SELECT e2.unit "
+ "FROM type e2 "
+ "WHERE e2.period=:period)");
query.setParameter("period", "2016-09");
list= query.list();

How to Determine Optimal MySQL Table Indexes, When Contents of WHERE Clause Vary?

I have the following 2 mysql_queries:
Query 1 (this query is repeated twice more for imgClass, and imgGender):
$imgFamily_query = "SELECT DISTINCT imgFamily FROM primary_images WHERE '$clause' ";
Query 2:
$query_pag_data = "SELECT imgId, imgURL, imgTitle, view, secondary FROM primary_images WHERE '$clause' ORDER BY imgDate DESC";
As you can see, the WHERE is controlled by a variable. This variable is calculated as follows:
$where_clauses = array();
if ($imgFamilyFalse && $imgClassFalse && $imgGenderFalse) {
$where_clauses[] = "1=1"; // default do-nothing clause
}
if ($imgFamilyTrue) {
$where_clauses[] = 'imgFamily=' . "'" . mysql_real_escape_string($_GET['imgFamily']) . "'";
}
if ($imgClassTrue) {
$where_clauses[] = 'imgClass=' . "'" . mysql_real_escape_string($_GET['imgClass']) . "'";
}
if ($imgGenderTrue) {
$where_clauses[] = 'imgGender=' . "'" . mysql_real_escape_string($_GET['imgGender']) . "'";
}
$clause = implode(' AND ', $where_clauses);
The WHERE clause is only dependant upon the following 3 columns:
imgFamily
imgClass
imgGender
However, depending upon the situation, a combination of any 1, 2, or 3 of those columns are utilized.
My question is, how should I go about setting up the indexes for primary_images in this situation? It is a 'read-only' table, so I'm not concerned about having too many indexes. I would like the table to be as efficient in its querying as possible.
I was thinking about using a Multiple Column Index, but because the first column in the Multiple Column Index may not be present, the Index would not work.
Is it possible to set up several Multiple Column Indexes? Or would it be better in this case to just place an index on each of the 3 columns in question?
I'm guessing imgGender will contain only 2 or 3 values - M, F and possible unknown? In that case, it makes a poor candidate for an index.
So, I think you can get away with 2 indices. Index one should use only imgClass, and will be hit when the imgFamily column isn't part of the where clause. Index two should be a compound index, using imgFamily and imgClass; this should be used even if imgClass isn't part of the where clause.
As per your situation its better to keep 3 separate indexes.