DataStax Stargate Document API - mongodb

What does the a JSON blob with search filters, allowed operators: $eq, $ne, $in, $nin, $gt, $lt, $gte, $lte, $exists in the Swagger documentation that is shown in the DataStax Document API Swagger UI, it's not that documented so I want to ask if the query string is based on MongoDB?

The Document API exposed on top of Cassandra is provided by the open source project Stargate, indeed developed by Datastax and embedded in their Saas solution Astra.
The JSON query String than you created is parsed and converted in a proper CQL query under the hood.
Source code doesn't lie you can find the full code here and specially parsing of the where clause here
public List<FilterCondition> convertToFilterOps(
List<PathSegment> prependedPath,
JsonNode filterJson) {
List<FilterCondition> conditions = new ArrayList<>();
if (!filterJson.isObject()) {
throw new DocumentAPIRequestException("Search was expecting a JSON object as input.");
}
ObjectNode input = (ObjectNode) filterJson;
Iterator<String> fields = input.fieldNames();
while (fields.hasNext()) {
String fieldName = fields.next();
if (fieldName.isEmpty()) {
throw new DocumentAPIRequestException(
"The field(s) you are searching for can't be the empty string!");
}
...

The query string is pretty similar in spirit to what you'd find with Mongo.
Here are some sample where clauses to give an idea:
{"name": {"$eq": "Eric"}} - simple enough, matches documents that have a field name with value Eric
{"a.age": {"$gt": 0}} - You can also reference nested fields in a document
{"friends.[0].name": {"$in": ["Cassandra"]}} - Array elements are referenced using [], this would match if the document's first friend is named Cassandra.
{"friends.*.age": {"$gte": 24}} - Wildcard * can be used to match any element in an array, or any field at a particular level of nesting. This matches any friend whose age is >= 24.

Related

MongoDB - Querying a field in a lower level of document

Issue with fetching the data of a particular field within a document
The followoing is my collection structure
colleciton mail
mailtype
criteria
triggerinfor
code ----> multiple codes are there.
description
status
Tried this but not working
db.getCollection('Mail').find(
{
"MailType" :"Printed",
"MailName" :"Welcomemail",
"programType":"Maile",
"criterias" :
{"triggerInformation":
{"code" :"MAIL007"},
{"description":"1234 Welcome maile"}
}
}
)
I have to retrieve the document with code MAIL007 only.. could some one help in getting a query for that
There are two ways to do it, depending on what you need:
1- Matching an exact nested document: this way, you are querying for documents that have a nested document that is exactly like the one in your search criteria.
db.getCollection('Mail').find(
{
"MailType" :"Printed",
"MailName" :"Welcomemail",
"programType":"Maile",
"criterias.triggerInformation": {
"code": "MAIL007",
"description": "1234 Welcome maile",
"status": "some status"
}
}
Notice that you need to explicitly inform a value to each of the nested document fields in your search criteria. If any field is missing the query will return nothing.
2- Querying a field inside a nested document: this way, you are querying for documents based on the value of one or more fields inside a nested document.
db.getCollection('Mail').find({
"MailType":"Printed",
"MailName":"Welcomemail",
"programType":"Maile",
$and: [
{"criterias.triggerInformation.code": "MAIL007"},
{"criterias.triggerInformation.description": "description":"1234 Welcome maile"}
]
})
In the code above you are querying for documents based on the values of the fields code and description inside the nested document criterias.triggerInformation.
You can find more info about querying nested documents at MongoDB's docs here

Mongodb query variable number of search terms

I am trying to design a query based on documents containing an array of metadata.
book = {
title : String,
metaData : [String]
}
To find the desired books I have another search string array containing multiple metadata terms. The length of the array can be variable in the number of metadata search terms present. How can I query to find only books that contain all the specified metadata search terms?
Example:
book1 - nature, trees, insects, fog, music
book2 - music, art, sports
Search using metadata of [music, sports] would yield book2.
How can I most efficiently design this query? Can I do this and avoid a nested query? Any help would be greatly appreciated.
You can do this by using the $all operator.
From the docs:
If, instead, you wish to find an array that contains both the elements "red" and "blank", without regard to order or other elements in the array, use the $all operator:
db.inventory.find( { tags: { $all: ["red", "blank"] } } )
MongoDB CRUD Operations: Query an array
You can use $all to get all the documents containing the given metadata strings.
Try:
let given_metadata_array = ["music", "sports"];
db.book.find({
metadata : {$all : given_metadata_array}
})
Read more about $all official documentation for detailed information.

spring data mongo - mongotemplate count with query hint

The mongo docs specify that you can specify a query hint for count queries using the following syntax:
db.orders.find(
{ ord_dt: { $gt: new Date('01/01/2012') }, status: "D" }
).hint( { status: 1 } ).count()
Can you do this using the mongo template? I have a Query object and am calling the withHint method. I then call mongoTemplate.count(query); However, I'm pretty sure it's not using the hint, though I'm not positive.
Sure, there are a few forms of this including going down to the basic driver, but assuming using your defined classes you can do:
Date date = new DateTime(2012,1,1,0,0).toDate();
Query query = new Query();
query.addCriteria(Criteria.where("ord_dt").gte(date));
query.addCriteria(Criteria.where("status").is("D"));
query.withHint("status_1");
long count = mongoOperation.count(query, Class);
So you basically build up a Query object and use that object passed to your operation, which is .count() in this case.
The "hint" here is the name of the index as a "string" name of the index to use on the collection. Probably something like "status_1" by default, but whatever the actual name is given.

MongoDB: Perform a text-search in a document field (using high-level API)

It may be related to this question
Basic GROUP BY statement using OPA MongoDB high level API.
I want to be able to retrieve a list of documents which "name" field value contains a given string.
Here's my documents list :
{name: "Charles-Hugo"},
{name: "Jean Pierre"},
{name: "Pierre Dupont"},
I want to be able to only retrieve documents which name contains the "Pierre" string: Jean Pierre, and Pierre Dupont.
I know this isn't possible with the MongoDB high-level API.
I've looked in the low-level API functions but I don't know what's the easiest way to retrieve my documents in safe Opa type.
Also I'd like to add skip/limit options to my query.
Any idea ?
The DbGen automation mechanism in Opa has support for this:
DbSet.iterator(/path/data[name =~ pattern])
As #Henri pointed out there is regular expression searching support in Opa since commit [enhance] DbGen: add case insensitive regex operator =~ what is very nice.
Mind that it is using $regex operator, not the full-text index and it may result with some performance loss :( As MongoDB documentation says $regex operator uses indexes in limited way - only for prefix search: pattern ^Jean. Searching for Jean anywhere in text will require full scan.
Personally, I am using full-text index feature of Mongo with Opa's "low-level" API for the $text command like this:
function list({float score, Article.id id}) textSearch(string query) {
function onfailure(failure) {
cat.error("textSearch({{~query}}): {failure}");
[];
}
function onsuccess(success) {
function aux(~{name,value}) {
name == "results";
}
match (List.filter(aux, success)) {
| [] :
// `results` field not found - error
onfailure(success);
| results:
cat.debug("textSearch({~{query}}): {results}");
function ({~score, obj: ~{id}}) {
~{score, id}
}
|> List.map(_, Bson.doc2opa(results) ? []);
}
}
opts = [H.str("search", query), H.doc("project", [H.i32("_id",0), H.i32("id",1)])];
// { search: query, project: {_id:0, id:1}, }
// |> Bson.opa2doc
outcome = MongoCommands.simple_str_command_opts(ll_db, db_name, "text", coll_name, opts);
MongoCommon.outcome_map(outcome, onsuccess, onfailure)
}
Feature is available in Mongo since 2.4 as experimental (you have to turn it on by special configuration option) and in 2.6 as stable (turned on by default).

Mongoose and limiting the results of field schema

I have a collection called "Binders"
In this collection I have a field called "docs" that references a "Docs" schema
I want to pull a "Binder" by id with findOne() which is no problem.
But I want to limit the returned "Docs" by a field comparison
I am somewhat new to mongoose but if i had pseudo my query...
Binder.findOne({_id: req.binder._id}, {$where {docs.type = 'type1'}}, function(error, binder) {
// So this would return my full binder but only the docs where their .type = 'type1'
});
Where I get lost is the limiting based on a Schema
{$where {docs.type = 'type1'}}
So if I pulled a binder and it had 50 docs, but none of the docs were of type1 I would still get my binder info, however there would be no documents in the Docs field.
Hope that makes sense.
If I'm following you right and docs is an array, then you can use the $elemMatch projection operator to do this:
Binder.findOne({_id: req.binder._id}, {docs: {$elemMatch: {type: 'type1'}}}, ...