Cassandra Lucene Index boolean syntax - java

I am performing a user search system in my Cassandra database. For that purpose I installed Cassandra Lucene Index from Stratio.
I am able to lookup users by username, but the problem is as follows:
This is my Cassandra users table and the Lucene Index:
CREATE TABLE user (
username text PRIMARY KEY,
email text,
password text,
is_verified boolean,
lucene text
);
CREATE CUSTOM INDEX search_main ON user (lucene) USING 'com.stratio.cassandra.lucene.Index' WITH OPTIONS = {
'refresh_seconds': '3600',
'schema': '{
fields : {
username : {type : "string"},
is_verified : {type : "boolean"}
}
}'
};
This is a normal query performed to Lookup a user by username:
SELECT * FROM user WHERE lucene = '{filter: {type : "wildcard", field : "username", value : "*%s*"}}' LIMIT 15;
My Question is:
How could I sort the returned results to ensure that any verified users are between the first 15 results in the query? (Limit is 15).

You can use this search:
SELECT * FROM user WHERE lucene = '{filter: {type:"boolean", must:[
{type : "wildcard", field : "username", value : "*%s*"},
{type : "match", field : "is_verified", value : true}
]}}' LIMIT 15;

Related

Query where clause over array elements inside jsonb PSQL

I have a JSON node on which I have to write PSQL query,
My table schema name(String),tagValues(jsonb). Example tagValue data is given below
Name_TagsTable
uid | name(String)| tagValues(jsonb)
-----+-------------------+-----------------------------
1 | myName | { "tags": [{"key":"key1","value" : "value1"}, {"key":"key1","value" : "value2"}, {"key":"key3","value" : "value3"}, {"key":"key4","value" : "value4"}] }
I need a query that gives me names for which
at least one of the tag in the tags list satisfy the condition
key = 'X' and value = 'Y'
Help me with the query. I am using PSQL 10.0
You can use the contains operator #> which also works with arrays
select *
from name_tagstable
where tagvalues -> 'tags' #> '[{"key": "x", "value": "y"}]';

Improving mongo query Performance(using Sub query )

Two documents can have same IMAGE_CONTENT_INSTANCE_HANDLE and state can be BOOKED or RELEASED
but I want all image instances handles which are only RELEASED state,
Currently I am doing this by firing two queries it introduced performance issues.
{
"state" : "RELEASED"
}
with projection { "imageContentInstance.handle" : 1}
i am iterating through the result which is coming out from this query
and firing another query as below and excluding the handles which are also in BOOKED state from adding to the list.So i gets handles only in the RELEASED state
while (cursor.hasNext()) {
ICI ici = objectMapper.readValue(result, ICI_COLLECTION_TYPE_REF);
String result = JSON.serialize(cursor.next());
try {
queryDocument = { "imageContentInstance.handle" : ici.getImageContentInstance().getHandle() , "state" : "BOOKED"}
Document bookedDoc = iciDAO.findOne(queryDocument);
if (null != bookedDoc)
LOGGER.debug("Calling continue and skipping booked state ");
continue;
}
iciHandles.add(ici.getImageContentInstance().getHandle().toString());
LOGGER.debug("ImageInstanceHandle is added to the lisr and the lise is "+iciHandles.size());
}
I want to achieve this in a single mongo query as an example query written in sql to increase performance .I really appreciate your comments .
SELECT *
FROM ici i
WHERE i.state = 'RELEASED'
AND NOT EXISTS
(SELECT * FROM ici ic WHERE ic.handle = i.handle AND ic.state = 'BOOKED'
);
example :
Suppose the documents are as below
{
"_id" : ObjectId("58c9f524fa8cd6a517cf5ddf"),
"imageContentInstance" : {
"handle" : "ICI:1234",
"key" : null,
}
"instanceHandle" : "LCI:RNBM12",
"state" : "BOOKED",
}
{
"_id" : ObjectId("58c9f524fa8cd6a517cf5ddf"),
"imageContentInstance" : {
"handle" : "ICI:1234",
"key" : null,
}
"instanceHandle" : "LCI:RNBM13",
"state" : "RELEASED",
}
{
"_id" : ObjectId("58c9f524fa8cd6a517cf5ddf"),
"imageContentInstance" : {
"handle" : "ICI:456",
"key" : null,
}
"instanceHandle" : "LCI:RNBM14",
"state" : "RELEASED"
}
My query should return the handle of the last document alone .ie, document with the status only with the RELEASED status .i am stuck, I really appreciate your ideas to improve this.
From Your question,i understand that you want all state ='Released' ans state!= 'BOOKED' which i think you have written little incorrect.
MongoDB query:
db.inventory.find({'state' : 'RELEASED'}})
Also go through mognodb docs
I hope it will help.I am also new to mongodb,if there is an error please make it correct.

How to create and publish Index using Java Client Programatically

Is it possible to programmatically create and publish secondary indexes using Couchbases Java Client 2.2.2? I want to be able to create and publish my custom secondary indexes Running Couchbase 4.1. I know this is possible to do with Couchbase Views but I can't find the same for indexes.
couchbase-java-client-2.3.1 is needed in order to programmatically create indexes primary or secondary. Some of the usable methods can be found on the bucketManger same that is used to upsert views. Additionally the static method createIndex can be used it support DSL and String syntax
There are a few options to create your secondary indexes.
Option #1:
Statement query = createIndex(name).on(bucket.name(), x(fieldName));
N1qlQueryResult result = bucket.query(N1qlQuery.simple(query));
Option #2:
String query = "BUILD INDEX ON `" + bucket.name() + "` (" + fieldName + ")";
N1qlQueryResult result = bucket.query(N1qlQuery.simple(query));
Option #3 (Actually multiple options here since method createN1qlIndex is overloaded
bucket.bucketManager().createN1qlIndex(indexName, fields, where, true, false);
Primary index:
// Create a N1QL Primary Index (ignore if it exists)
bucket.bucketManager().createN1qlPrimaryIndex(true /* ignore if exists */, false /* defer flag */);
Secondary Index:
// Create a N1QL Index (ignore if it exists)
bucket.bucketManager().createN1qlIndex(
"my_idx_1",
true, //ignoreIfExists
false, //defer
Expression.path("field1.id"),
Expression.path("field2.id"));
or
// Create a N1QL Index (ignore if it exists)
bucket.bucketManager().createN1qlIndex(
"my_idx_2",
true, //ignoreIfExists
false, //defer
new String ("field1.id"),
new String("field2.id"));
The first secondary index (my_idx_1) is helpful if your document is something like this:
{
"field1" : {
"id" : "value"
},
"field2" : {
"id" : "value"
}
}
The second secondary index (my_idx_2) is helpful if your document is something like this:
{
"field1.id" : "value",
"field2.id" : "value"
}
You should be able to do this with any 2.x, once you have a Bucket
bucket.query(N1qlQuery.simple(queryString))
where queryString is something like
String queryString = "CREATE PRIMARY INDEX ON " + bucketName + " USING GSI;";
As of java-client 3.x+ there is a QueryIndexManager(obtained via cluster.queryIndexes()) which provides an indexing API with the below specific methods to create indexes:
createIndex(String bucketName, String indexName, Collection<String> fields)
createIndex(String bucketName, String indexName, Collection<String> fields, CreateQueryIndexOptions options)
createPrimaryIndex(String bucketName)
createPrimaryIndex(String bucketName, CreatePrimaryQueryIndexOptions options)

Empty JSON vs null conversions to a

I'm trying to create an HTTP PUT endpoint in Java that takes in a delta json from the front end and I'm having some trouble figuring out how to implement "nulls".
For example if we have a database model that looks like
id : 1
firstname : Luke
lastname : Xu
age : 24
fav_color : Red
And we send over a PUT request to /person/1 with a json of {age : 25}. Currently, I have a JOOQ pojo to converts to following JSON to a java model but the problem is it is also updating my database values to be null.
There's no difference between
{age : 25}
and
{id : 1,
firstname : null,
lastname : null,
age : 25,
fav_color : null}
Once it hits my Java end point the java model just sets both cases to "null" and there's no difference between a passed in null or the value wasn't being passed in at all.
I also considered processing an input stream (type JSON) but the problem with this is that our JSON names have to be named exactly the same as the database column names which is also kind of unreasonable.
What is the standard for editing the database if we only want to send a "delta json"????
Since you're using jOOQ, I'd suggest you directly pass the JSON values to the jOOQ UpdatableRecord, which can in fact distinguish between:
null meaning not initialised (or default)
null meaning null
It does so by maintaining a changed() flag for each individual column.
For instance:
{age : 25}
... translates to this Java code:
// record.set(USER.ID, 1) I suspect this is still necessary...?
record.set(USER.AGE, 25);
record.update();
... and to this SQL statement:
UPDATE users
SET age = 25
WHERE id = 1
whereas
{id : 1,
firstname : null,
lastname : null,
age : 25,
fav_color : null}
... translates to this Java code
record.set(USER.ID, 1);
record.set(USER.FIRSTNAME, null);
record.set(USER.LASTNAME, null);
record.set(USER.AGE, 25);
record.set(USER.FAV_COLOR, null);
... and to this SQL statement
UPDATE users
SET firstname = null,
lastname = null,
age = 25,
fav_color = null
WHERE id = 1

Spring data mongodb removes a positional operator from "$unset" update query part

I have a collection of users:
> db.users.find().pretty()
{
"_id" : ObjectId("544ab933e4b099c3cfb62e12"),
"token" : "8c9f8cf4-1689-48ab-bf53-ee071a377f60",
"categories" : [
DBRef("cue_categories", ObjectId("544ab933e4b099c3cfb62e10")),
DBRef("cue_categories", ObjectId("544ab933e4b099c3cfb62e11"))
]
}
I want to find all users who have (let's say) ObjectId("544ab933e4b099c3cfb62e10") category and remove it (because this category was deleted and I don't want users to refer to it anymore).
The valid query to do it in JSON format would be:
db.users.update({
categories:{
$in:[
DBRef("cue_categories", ObjectId("544ab933e4b099c3cfb62e10"))
]
}
},
{
$unset:{
"categories.$":true
}
})
Here's a Spring mongodb query:
Query query = new Query();
query.addCriteria(Criteria.where("categories.$id").in(categoryIds));
Update update = new Update();
update.unset("categories.$");
operations.updateMulti(query, update, User.class);
In order to make an appropriate DB reference I have to provide a list of category IDs, each category ID (in categoryIds) is an instance of org.bson.types.ObjectId.
The problem is that the result query turns out to be without a positional operator:
DEBUG o.s.data.mongodb.core.MongoTemplate - Calling update using
query: { "categories.$id" : { "$in" : [ { "$oid" :
"544ab933e4b099c3cfb62e10"}]}} and update: { "$unset" : { "categories"
: 1}} in collection: users
So the update part must be { "$unset" : { "categories.$" : 1}}
P.S.
I managed to get around by falling back to the plain Java driver use
DBObject query = new BasicDBObject("categories.$id", new BasicDBObject("$in", categoryIds));
DBObject update = new BasicDBObject("$unset", new BasicDBObject("categories.$", true));
operations.getCollection("users").updateMulti(query, update);
But my question still remains open!
P.S.S.
My case is very similar to Update Array Field Using Positional Operator ($) Does Not Work bug and looks like it was fixed for versions 1.4.1 and 1.5. That being said I use spring-data-mongodb version 1.5.1. And I'm confused. Does anybody have a clue?
You can not use positional $ operator with unset as per MongoDB documentation. It will set the value as Null. https://docs.mongodb.com/manual/reference/operator/update/positional/

Categories

Resources