IN operator in Couchbase Lite - couchbase-lite

I need to query something like
SELECT * FROM `sample` WHERE id IN ["123", "456"]
This is converted into QueryBuilder as below
QueryBuilder
.select(SelectResult.all())
.from(DataSource.database("sample"))
.where(Expression.property("id")
.in([
Expression.string("123"),
Expression.string("456")
])
)
This doesn't work, and return empty list of result, any idea?

I see from your comments that your code worked (it was false negative). Yet I'll share an approach which may be useful in case you need to use the like operator against multiple wildcarded (%) expressions. Sample is in Kotlin language:
val list = listOf("123", "456")
val items = list.map { Meta.id.like(Expression.string("$it-%")) }.toMutableList()
val whereExpression = items
.fold(items.removeAt(0)) { chain, next -> chain.or(next) }
val query = QueryBuilder.select(
SelectResult.expression(Meta.id),
SelectResult.all()
).from(DataSource.database(this.db)).where(whereExpression)
val results = query.execute()
val resultList = results.allResults()

Related

Flux returns unsorted data for StepVerifier

I expect to receive two elements after writing three to the database. The query returns a Flux, which returns the elements unsorted.
#Test
fun `SUCESSFULLY query pending purchases`() {
// arrange
val arrived = TestDataFactory.buchungssatzEntity(
sequentialId = 1,
arrived = true
)
val pending = TestDataFactory.buchungssatzEntity(
sequentialId = 2,
arrived = false
)
val next_pending = TestDataFactory.buchungssatzEntity(
sequentialId = 3,
arrived = false
)
// act
buchhaltungWriter.save(arrived)
buchhaltungWriter.save(pending)
buchhaltungWriter.save(next_pending)
val purchases = inventoryFinder.findAllPendingPurchases()
// assert
StepVerifier.create(purchases)
.expectNext(pending)
.expectNext(next_pending)
.verifyComplete()
}
This always throws
expected value: BuchungssatzEntity(... sequentialId=2 ...); actual value: BuchungssatzEntity(... sequentialId=3 ...)
I do not want to add sorting to the database query, it's a waste of time. How can I test Flux with 'all of these elements but in any order' or should I just go for a Mono in this case, return a list and do the rest myself? Then again, that's not why I'm using reactive.
PS: Goal of this test is to verify that my Spring query language statement filters correctly.
-------- UPDATE
I solved it by using
StepVerifier.create(inventoryFinder.findAllPendingPurchases())
.recordWith { listOf<PurchasesModel>() }
.thenConsumeWhile { i: Any? -> purchases.contains(i) }
.consumeRecordedWith{ }
.verifyComplete()
One way to do that is to use the thenConsumeWhile operator along with expectNextCount. If there is any element in the sequence that doesn't match, the StepVerifier will error.
In Java:
List<Item> pendingItems = List.of(pending, next_pending);
Flux<Item> items = inventoryFinder.findAllPendingPurchases();
StepVerifier.create(items)
.expectNextCount(2) //expecting 2 elements
.verifyComplete();
StepVerifier.create(items)
.thenConsumeWhile((i) -> pendingItems.contains(i)) // check if element was expected
.verifyComplete();

What's a concise way of sorting and grouping a set in Kotlin?

From a set of Comparable objects I would like to get a sorted list of sets of objects, sorted by their natural order.
This is my solution:
val set: Set<Comparable<A>> = makeThings()
val sorted = set.sorted()
val sortedAndGrouped = mutableListOf(mutableSetOf(sorted.first()))
for(element in sorted.drop(1)) {
val randomElementOfLastGroup = sortedAndGrouped.last().first()
val doesNotBelongToLastGroup = randomElementOfLastGroup.compareTo(element) != 0
if(doesNotBelongToLastGroup)
sortedAndGrouped.add(mutableSetOf())
sortedAndGrouped.last().add(element)
}
I would like to know if there is a more concise alternative in Kotlin.
If not, is there one using Java 8 features or a library like Guava?
I would try something like this:
fun <A : Comparable<A>> alternativeSortAndGroup(set: Set<A>): List<Set<A>> =
set.sorted().groupBy { it }.values.map { it.toSet() }

How to create programmatically single LINQ query w/ OR between Where() clauses (.Where(fn) OR .Where(fn) OR .Where(fn)) programatically

I'd like to know it is it possible to create programmatically single LINQ query (for EntityFramework 6) with N .Where() clauses, but with OR between these .Where() clauses.
Imagine IQueryable object defined like:
var query = dbContext.MyTable.Where(mt => mt.TimeStamp >= DateBegin);
What I need else is add N (unknown number) of Where clauses, but with OR condition between them.
Image list of some object:
List<MyObject> myObj =
new List<MyObject>({new MyObject {val = "a" }, new MyObject { val = "b"}}); //In real code there is more than 1 property.
then I'd like to add Where() clauses to query like:
myObj.ForEach(mo =>{
// THIS CREATES -AND- BETWEEN WHERE CLAUSES, BUT I NEED -OR-
query.Where(q=>q.MyValue == mo.val); // In real code there is more than 1 property to compare
});
I was thinking about .Union() beteween queries, but It could generate union between separated queries and it's not optimal I think.
Thanks!
Here's the solution: linq-to-entities-combining-predicates
Or course is necessary to use "latest" answer:
Copy/Paste class ParameterRebinder
Copy/Paste static class Utility
Usage:
Expression<Func<Car, bool>> theCarIsRed = c => c.Color == "Red";
Expression<Func<Car, bool>> theCarIsCheap = c => c.Price < 10.0;
Expression<Func<Car, bool>> theCarIsRedOrCheap = theCarIsRed.Or(theCarIsCheap);
var query = carQuery.Where(theCarIsRedOrCheap);
Because in my solution is N of expressions, I take first expression and then append other expressions in ForEach cycle.
var firstExpression = expressionList.First();
expressionList.Skip(1).ToList().ForEach(ex => { firstExpression = firstExpression.Or(ex); });

Scala Code - Immutable Set Issues

I'm learning Scala and I would like to convert some of my old algorithms code to Scala.
I have very simple Java code which prints superSet (a combination of all possible sets including empty set and the set itself).
public static Set<Set<Integer>> createSuperSet(Set<Integer> originalSet){
Set<Set<Integer>> superSet = new HashSet<Set<Integer>>();
if (originalSet.size() == 0){
Set<Integer> empty = new HashSet<Integer>();
superSet.add(empty);
return superSet;
}
List<Integer> list = new ArrayList<Integer>(originalSet);
Integer head = list.get(0);
Set<Integer> rest = new HashSet<Integer>(list.subList(1, list.size()));
for (Set<Integer> set : createSuperSet(rest)){
Set<Integer> newSet = new HashSet<Integer>();
newSet.add(head);
newSet.addAll(set);
superSet.add(newSet);
superSet.add(set);
}
return superSet;
}
Now I'm trying to achieve the same functionality in Scala:
def createSuperSet(originalSet: Set[Int]): Set[Set[Int]] ={
val superSet = Set[Set[Int]]()
originalSet.toList match {
case List() => {superSet + Set[Int]()}
case head::restAsList => {
val rest = restAsList.toSet[Int]
val result = createSuperSet(rest)
result.foreach(f=>{
val newSet:Set[Int] = f + head
superSet + f +newSet
})
superSet
}
}
}
but unfortunately this code returns empty Set. I'm suspecting that this issue happens due to Immutable collection usage. I was trying to run it in Debugger and I see that recursive call to function always returns empty set and my code is never getting into foreach function.
Please help. Any thoughts are welcomed.
In idiomatic scala the + (and -, ++, etc) operator as applied to immutable collections creates a new collection - otherwise they would not be immutable. Instead you have to combine the modification with another piece of syntactic sugar under which if you append = to an operator it assigns the result of the operator to the left-hand variable: superSet += f + newSet.
I solved the problem this way:
def createSuperSet(originalSet: Set[Int]): Set[Set[Int]] ={
var superSet = Set[Set[Int]]()
originalSet.toList match {
case List() => {superSet + Set[Int]()}
case head::restAsList => {
val rest = restAsList.toSet[Int]
val result = createSuperSet(rest)
result.map(f=>{
superSet = superSet + f+ (f+head)
})
superSet
}
}
}
running println(createSuperSet(Set[Int](1,2,3))
prints
Set(Set(), Set(3, 1), Set(2), Set(2, 1), Set(3, 2), Set(3), Set(3, 2, 1), Set(1))
but I'll be very glad to find out if there is any more elegant solution

Linq - How to query specific columns and return a lists

I am trying to write a linq query that will only return certain columns from my entity object into a list object.
Below is my code which produces an error(can't implicitly convert a generic list of anonymous types to a generic list of type TBLPROMOTION):
IQueryable<TBLPROMOTION> matches = webStoreContext.TBLPROMOTION.Include("TBLSTORE").Include("LKPROMOTIONTYPE");
List<TBLPROMOTION> promotionInfo = null;
promotionInfo = (from p in matches
orderby p.PROMOTION_NM descending
select new { p.EFFECTIVE_DT, p.EXPIRE_DT, p.IS_ACTIVE,
p.PROMOTION_DESC, p.PROMOTION_ID, p.PROMOTION_NM }).ToList();
What would be the best way to accomplish this. I do not want to do a "select p" in this case and return all the columns associated with the query.
thanks in advance,
Billy
Can't you do var promotionInfo = () and get a list of anonymous types?
Okay, basically you can not cast an Anonymous type to a known type like TBLPROMOTION.
ofcourse, you can say var promotionInfo = and then get an IEnumerable<{Anonymoustype}> and use that to do, what you were wanting to do with promotionInfo.
Also, personally I prefer the Fluent version of a linq query, easy on the eyes, good programming diet, at least for me :)
var promotionInfo = matches
.OrderByDescending( p => p.PROMOTION_NM)
.Select( p => new { p.EFFECTIVE_DT,
p.EXPIRE_DT,
p.IS_ACTIVE,
p.PROMOTION_DESC,
p.PROMOTION_ID,
p.PROMOTION_NM})
.ToList();
If you're moving from a L2E query to a Type already defined, you may need a step between. I haven't tried to compile this but something like:
List<TBLPROMOTION> promotions = new List<TBLPROMOTION>();
var results = from p in matches
orderby p.PROMOTION_NM descending
select new
{
p.EFFECTIVE_DT,
p.EXPIRE_DT,
p.IS_ACTIVE,
p.PROMOTION_DESC,
p.PROMOTION_ID,
p.PROMOTION_NM
};
foreach (var v in results)
{
promotions.Add(new TBLPROMOTION(v.EFFECTIVE_DT, v.EXPIRE_DT, v.IS_ACTIVE,
v.PROMOTION_DESC, v.PROMOTION_ID, v.PROMOTION_NM));
}
Based on the comment below, you might try something like:
foreach(var v in results)
{
TBLPROMOTION temp = new TBLPROMOTION();
temp.EFFECTIVE_DT = v.EFFECTIVE_DT;
temp.EXPIRE_DT = v.EXPIRE_DT;
temp.IS_ACTIVE = v.IS_ACTIVE
// Assign Other Properties
promotions.Add(temp);
}
.......
Sorry: Just read the addition to the top.
Are you sure that none of the fields you're leaving out (instead of saying "select p") are required for a TBLPROMOTION object? Also, sense your TBLPROMOTION object is going to have properties (and therefore memory allocated) for those skipped fields, why not just use an annonymous type or set up a helper class that contains only your needed properties?
#Billy, following code worked for me.
List<TBLPROMOTION> promotionInfo =
(from p in matches
orderby p.PROMOTION_NM descending
select new TBLPROMOTION(p.EFFECTIVE_DT, p.EXPIRE_DT, p.IS_ACTIVE,
p.PROMOTION_DESC, p.PROMOTION_ID, p.PROMOTION_NM)
).ToList();
did you try
select new TBLPROMOTION {.....
instead of
select new {.....
List<TBLPROMOTION> promotionInfo = null;
promotionInfo = (from p in matches
orderby p.PROMOTION_NM descending
select new TBLPROMOTION { COL1 = p.EFFECTIVE_DT, COL2 = p.EXPIRE_DT, COL3 = p.IS_ACTIVE... }).ToList();
Where COL1, COL2, ... are the names of the properties on TBLPROMOTION you wish you populate.
If you want a subset of the table you have 2 options:
#Fredou mentioned select new TBLPROMOTION{...}
other way is to create a custom DTO which has the exact properties & select them instead like:
List promotionInfo = ...
select new TBLPROMOTION_DTO{
Effective_dt = ...
}
HTH

Resources