With android Room, how to delete items more than 1000? - sql

got crash when the ids is > 999
android.database.sqlite.SQLiteException: too many SQL variables (code 1): ,
while compiling: delete from data where ids in (?,?,...)
saw this seems there is max limit to 999.
how to delete more than 1000 with Room?

Probably you have a list of ids to delete. Open a transaction, split the list in sublist and execute the SQL delete operation once for sublist.
For more information about Room the official documentation about Transactions with Room.
I didn't test the following code, but I think that it accomplishes your need.
#Dao
public interface DataDao {
#Delete("delete from data where ids in :filterValues")
long delete(List<String> filterValues)
#Transaction
public void deleteData(List<Data> dataToDelete) {
// split the array in list of 100 elements (change as you prefer but < 999)
List<List<Data>> subLists=DeleteHelper.chopped(dataToDelete, 100);
List<String> ids=new ArrayList<>();
for (List<Data> list: subList) {
list.clear();
for (Data item: list) {
ids.add(item.getId());
}
delete(ids);
}
}
}
public abstract class DeleteHelper {
// chops a list into non-view sublists of length L
public static <T> List<List<T>> chopped(List<T> list, final int L) {
List<List<T>> parts = new ArrayList<List<T>>();
final int N = list.size();
for (int i = 0; i < N; i += L) {
parts.add(new ArrayList<T>(
list.subList(i, Math.min(N, i + L)))
);
}
return parts;
}
}
I hope this help.

I think there are two ways to solve it.
First, chop chop your list and runs multiple times with delete method. (just like #xcesco answered)
Second, you can write very long query and run it with #RawQuery.
#RawQuery
abstract int simpleRawQuery(SupportSQLiteQuery sqliteQuery)
#Transaction
public int deleteData(List<Long> pkList) {
SimpleSQLiteQuery query = new SimpleSQLiteQuery("DELETE FROM tb WHERE _id IN (" + StringUtils.join(pkList,",") + ")";
return simpleRawQuery(query)
}

Related

How do I create an application that prompts the user for an integer and returns the number of digits it has?

I've started writing this code down, and I want to find the return of the number digits it has after the user prompts for the an integer. Where do I begin with this solution?
I'm still currently new to Dr Java coding. However, I've tried researching these methods, and I cannot find an example for this solution.
public class Recursion {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter an integer.");
int digit = input.nextInt();
input.close();
}
}
I expect it needs a recursion or method for this problem, and I believe it needs to return to the number digit, but I am not sure if it's correct.
you can use this function to count number of digits:
function digits_count(n) {
var count = 0;
if (n >= 1) ++count;
while (n / 10 >= 1) {
n /= 10;
++count;
}
return count;
}

Comparator in binary search

I am not sure how to write comparator for Collectionos.binarySearch(). Can anyone help ? sample code:
List<Object> list1 = new ArrayList<>();
List<List<Object>> list2 = new ArrayList<>();
//loop starts
// adds elements into list1
list1.add(values);//values is an object containing elements like [3, John, Smith]
if (list2.size() == 0) {
list2.add(list1);//first element
} else {
if (index >= 0) {
int index = Collections.binarySearch(list2, list1, comparator);
list2.add(index, list1);//I want to add these elements in ascending order ?
}
}
//loop ends
How do I write comparator, so that elements in list 2 are added in ascending or descending order.
You can use an anonymous class which implements a Comparator<List<Object>>:
int index = Collections.binarySearch(list2, list1, new Comparator<List<Object>>() {
#Override
public int compare(List<Object> o1, List<Object> o2) {
// Your implementation here
return 0;
}
});
You could implement an IComparer<List<Object>> class, or use a lambda expression.
You just need to create a class that implements the Comparator interface.
For example, you can do this inline with an anonymous class:
Comparator<List<Object>> comparator = new Comparator<List<Object>>() {
#Override
public int compare(List<Object> x, List<Object> y) {
// custom logic to compare x and y here. Return a negative number
// if x < y, a positive number if x > y, and 0 otherwise
}
};
Collections.binarySearch(list, comparator);

implement feedback in lucene

Can someone give me hints to apply pseudo-feedback in lucene. I can not find much help on google. I am using Similarity classes.
Is there any class in lucene which I can extend to implement feedback ?
thanks.
Assuming you are referring to this relevance feedback method, Once you have the TopDocs for your original query, iterate through how ever many (let's say we'll want the top 25 terms for the top 25 docs of the original query) records you desire, and call IndexReader.getTermVectors(int), which will grab the information you need. Iterate through each. while storing the term frequencies in a hash map would be the implementation the immediately occurs to me.
Something like:
//Get the original results
TopDocs docs = indexsearcher.search(query,25);
HashMap<String,ScorePair> map = new HashMap<String,ScorePair>();
for (int i = 0; i < docs.scoreDocs.length; i++) {
//Iterate fields for each result
FieldsEnum fields = indexreader.getTermVectors(docs.scoreDocs[i].doc).iterator();
String fieldname;
while (fieldname = fields.next()) {
//For each field, iterate it's terms
TermsEnum terms = fields.terms().iterator();
while (terms.next()) {
//and store it
putTermInMap(fieldname, terms.term(), terms.docFreq(), map);
}
}
}
List<ScorePair> byScore = new ArrayList<ScorePair>(map.values());
Collections.sort(byScore);
BooleanQuery bq = new BooleanQuery();
//Perhaps we want to give the original query a bit of a boost
query.setBoost(5);
bq.add(query,BooleanClause.Occur.SHOULD);
for (int i = 0; i < 25; i++) {
//Add all our found terms to the final query
ScorePair pair = byScore.get(i);
bq.add(new TermQuery(new Term(pair.field,pair.term)),BooleanClause.Occur.SHOULD);
}
}
//Say, we want to score based on tf/idf
void putTermInMap(String field, String term, int freq, Map<String,ScorePair> map) {
String key = field + ":" + term;
if (map.containsKey(key))
map.get(key).increment();
else
map.put(key,new ScorePair(freq,field,term));
}
private class ScorePair implements Comparable{
int count = 0;
double idf;
String field;
String term;
ScorePair(int docfreq, String field, String term) {
count++;
//Standard Lucene idf calculation. This is calculated once per field:term
idf = (1 + Math.log(indexreader.numDocs()/((double)docfreq + 1))) ^ 2;
this.field = field;
this.term = term;
}
void increment() { count++; }
double score() {
return Math.sqrt(count) * idf;
}
//Standard Lucene TF/IDF calculation, if I'm not mistaken about it.
int compareTo(ScorePair pair) {
if (this.score() < pair.score()) return -1;
else return 1;
}
}
(I make no claim that this is functional code, in it's current state.)

Java executor service How to return total success and total failed record at once

I am inserting records in database using executorserive. Lets say saving 100 records by creating 5 batches each containing 20 records.
ExecutorService e = Executors.newFixedThreadPool(3);
Collection c= new ArrayList();
while (someloop)
{
c.add(mySaveMehtod());
}
List<Future<String>> list = e.invokeAll(c);
Iterator<Future<String>> i= list.iterator();
Future<String> f=null;
while(i.hasNext())
{
f= itr.next();
}
Strin str = f.get();
While processing there might be error for some records and some records will process successfully.
Once process finishes I want to collect total successfully processed and total failed record at once.
Can anybody let me know how I can achieve this ?
Thanks.
Assuming that you know if an INSERT of a record was successful immediately after executing the SQL, you can simply use two AtomicIntegers. You declare them and set to 0 before running batch insert jobs, and increment them in these jobs. Operations on AtomicIntegers are thread safe, so you don't need to worry about synchronization. For example:
public static void main() {
AtomicInteger nSuccess = new AtomicInteger(0);
AtomicInteger nFailed = new AtomicInteger(0);
// add batch insert jobs
// wait for jobs to finish
System.out.println("succeeded: " + nSuccess.get() + " failed: " + nFailed.get());
}
class BatchInserter implements Runnable {
public void run() {
for (int i = 0; i < 20; i++) {
if (insertRecord(i)) {
nSuccess.getAndIncrement();
} else {
nFailed.getAndIncrement();
}
}
}
}

How to multiply several fields in a tuple by a given field of the tuple

For each row of data, I would like to multiply fields 1 through N by field 0. The data could have hundreds of fields per row (or a variable number of fields for that matter), so writing out each pair is not feasible. Is there a way to specify a range of fields, sort of like the the following (incorrect) snippet?
A = LOAD 'foo.csv' USING PigStorage(',');
B = FOREACH A GENERATE $0*($1,..);
A UDF could come in handy here.
Implement exec(Tuple input) and iterate over all fields of the tuple as follows (not tested):
public class MultiplyField extends EvalFunc<Long> {
public Long exec(Tuple input) throws IOException {
if (input == null || input.size() == 0) {
return null;
}
try {
Long retVal = 1;
for (int i = 0; i < input.size(); i++) {
Long j = (Long)input.get(i);
retVal *= j;
}
return retVal;
} catch(Exception e) {
throw WrappedIOException.wrap("Caught exception processing input row ", e);
}
}
}
Then register your UDF and call it from your FOREACH.