How can i apply nested string operators in projection? - spring

I need to create an implementation using aggregator framework that executes this projection:
{ $project : { code: $toUpper : { $substr : ["$vendor", 0, 2 ] } } }
So far I have not found a way to express the concatenation of the $substr and $toUpper operation using Spring. I have tried with this construction and other similar variants, but I have not succeeded.
ProjectionOperation projection = project()
.and("vendor").substring(0, 2).toLower().as("code");
Can anyone give me an idea of how to do this?

Here is the way to do it:
project()
.and(ToLower.lowerValueOf(SubstrCP.valueOf("vendor").substringCP(0, 2)))
.as("code")

Related

How to use MongoDB $let in Spring Data MongoOperation

MongoDB returns $count as an array of single element. And I want to transform it into an object(int or String) so I can map it directly to the String field in my class. For that I have used the projection below which do transform it into a int32 object. Now, I want to translate the below projection to Spring Data MongoOperation aggregate
{
$project:{
"count":
{
$let:{
"vars":{
"elem":
{ $arrayElemAt:["$count",0] }
},
"in":{
"count" :"$$elem.totalVideos"
}
}
}
}
}
Reading the documentation I built part of it as below.
Let.define(Let.ExpressionVariable.newVariable("elem").
forExpression(ArrayOperators.ArrayElemAt.arrayOf("count").elementAt(0)))
But not sure if I am doing it right. Does anybody know how this can be done in Spring Data?
Thanks in advance
Pretty implementation
Instead of "count" :"$$elem.totalVideos" we apply "count" : {"$toInt" : "$$elem.totalVideos"}
You may use ConvertOperators.ToString, ConvertOperators.ToLong, etc...
Aggregation.project()
.and(
Let.define(Let.ExpressionVariable
.newVariable("elem")
.forExpression(
ArrayOperators.ArrayElemAt.arrayOf("count").elementAt(0)
)
).andApply(PropertyExpression.property("count").definedAs(ToInt.toInt("$$elem.totalVideos")))
//.andApply(ToInt.toInt("$$elem.totalVideos"))
).as("count")
Less Pretty implementation
Aggregation.project()
.and(
Let.define(Let.ExpressionVariable
.newVariable("elem")
.forExpression(
ArrayOperators.ArrayElemAt.arrayOf("count").elementAt(0)
)
).andApply(new AggregationExpression() {
#Override
public Document toDocument(AggregationOperationContext context) {
return new Document("count", "$$elem.totalVideos");
}
})
).as("count")

How to Conditionally reverse a list with in a compareBy in Kotlin

I have the following code
val sortMethod = compareBy<Item> {
when (model.preferences.getSortMethod()) {
TITLE -> it.getTitle().toLowerCase(Locale.getDefault())
DATE -> it.getSortableDateString()
AUTHOR -> it.getAuthor().toLowerCase(Locale.getDefault())
DATE_ADDED -> it.getSortableDateAddedString()
}
}.thenBy { it.getTitle().toLowerCase(Locale.getDefault()) }
which i then use on Lists like so
myItems.sortedWith(sortMethod)
I like this solution and I think it's very elegant. However, i would like to add the ability to sort ascendingly/descendingly as well.
So I am asking how do I add a conditional .reverse() to my sortMethod? I am very reluctant to put a if condition on every one of my sort calls and would like to get it all done in the sortMethod logic
You can do it like this:
list.sortedWith(if (sortAscending) sortMethod else sortMethod.reversed())
I suggest removing Locale.getDefault() since toLowerCase() is equivalent to toLowerCase(Locale.getDefault()).
private fun List<Item>.sort() : List<Item>{
if (model.preferences.isSortedAscendingly()){
return this.sortedWith(sortMethod)
}
return this.sortedWith(sortMethod).reversed()
}
Decided my solution will be using the above extension function, but if anyone has a better way i would love to hear.
Use let()?
private fun List<Item>.sort() = sortedWith(sortMethod).let {
if (model.preferences.isSortedAscendingly())
it
else
it.reversed()
}

How can I do a WpGraphQL query with a where clause?

This works fine
query QryTopics {
topics {
nodes {
name
topicId
count
}
}
}
But I want a filtered result. I'm new to graphql but I see a param on this collection called 'where', after 'first', 'last', 'after' etc... How can I use that? Its type is 'RootTopicsTermArgs' which is likely something autogenerated from my schema. It has fields, one of which is 'childless' of Boolean. What I'm trying to do, is return only topics (a custom taxonomy in Wordpress) which have posts tagged with them. Basically it prevents me from doing this on the client.
data.data.topics.nodes.filter(n => n.count !== null)
Can anyone direct me to a good example of using where args with a collection? I have tried every permutation of syntax I could think of. Inlcuding
topics(where:childless:true)
topics(where: childless: 'true')
topics(where: new RootTopicsTermArgs())
etc...
Obviously those are all wrong.
If a custom taxonomy, such as Topics, is registered to "show_in_graphql" and is part of your Schema you can query using arguments like so:
query Topics {
topics(where: {childless: true}) {
edges {
node {
id
name
}
}
}
}
Additionally, you could use a static query combined with variables, like so:
query Topics($where:RootTopicsTermArgs!) {
topics(where:$where) {
edges {
node {
id
name
}
}
}
}
$variables = {
"where": {
"childless": true
}
};
One thing I would recommend is using a GraphiQL IDE, such as https://github.com/skevy/graphiql-app, which will help with validating your queries by providing hints as you type, and visual indicators of invalid queries.
You can see an example of using arguments to query terms here: https://playground.wpgraphql.com/#/connections-and-arguments

Why QueryContainer is not updating from a Descriptor NESt C#

Hi I have following descriptors in my NEST query...
queryContainer.DateRange(b => dateRangeDescriptor);
queryContainer.MatchPhrase(b => matchPhraseDescriptor);
And finally I use this QueryContainerDescriptor in the following BoolQueryDescriptor
boolDescriptor.Must(q => queryContainer);
The problem is although I could see values in my dateRangeDescriptor as well as matchPhraseDescriptor, it is not available in side queryContainer.
Not sure what is going wrong here.
Must has the following overloads (in NEST 2.x)
public BoolQueryDescriptor<T> Must(
params Func<QueryContainerDescriptor<T>, QueryContainer>[] queries)
{
// impl
}
public BoolQueryDescriptor<T> Must(
IEnumerable<Func<QueryContainerDescriptor<T>, QueryContainer>> queries)
{
// impl
}
public BoolQueryDescriptor<T> Must(
params QueryContainer[] queries)
{
// impl
}
So you need to pass a collection of queries to apply multiple must clauses rather than adding them all to one QueryContainer.

java: how to limit score results in mongo

I have this mongo query (java):
TextQuery.queryText(textCriteria).sortByScore().limit(configuration.getSearchResultSize())
which performs a text search and sort by score.
I gave different wiehgt to different fields in the docuemnt, and now I'd like to retrieve only those results with score lower then 10.
is there a way to add that criteria to the query?
this didn't work:
query.addCriteria(Criteria.where("score").lt(10));
if the only way is to use aggregation - I need a mongoTemplate example for that.
in other words
how the do I translate the following mongo shell aggregate command, to java spring's mongoTemplate command??
can't find anywhere how to use the aggregate's match() API with the $text search component (the $text is indexed on several different fields):
db.text.aggregate(
[
{ $match: { $text: { $search: "read" } } },
{ $project: { title: 1, score: { $meta: "textScore" } } },
{ $match: { score: { $lt: 10.0 } } }
]
)
Thanks!
Please check with below code sample, MongoDB search with pagination code in java
BasicDBObject query = new BasicDBObject()
query.put(column_name, new BasicDBObject("$regex", searchString).append("$options", "i"));
DBCursor cursor = dbCollection.find(query);
cursor.skip((pageNum-1)*limit);
cursor.limit(limit);
Write a loop and and call the above code from loop and pass the values like pageNum starts from 1 to n and limit depends on your requirement. check the cursor is empty or not. If empty skip the loop if not continue calling the above code base.
Hope this will be helpful.

Resources