Copy MongoDb indexes between databases - mongodb

I am trying to copy mongo indexes between two environments. Checked the API and found no direct method of doing it. So I started writing a script that connects to one db, iterates over the collections, grabs indexes, mutates them (because getIndexes() and ensureIndex()) have different format), connects to the other db, wipes the indexes and copies the new ones in.
This all feels slightly over the top so I think that I must be missing something.
Any suggestions/good practices? Apart from having an index creation strategy.
Cheers!

Please run it on the database that you want to copy indexes.
db.getCollectionNames().forEach(function(collection) {
indexes = db[collection].getIndexes();
indexes.forEach(function (c) {
opt = ''
ixkey = JSON.stringify(c.key, null, 1).replace(/(\r\n|\n|\r)/gm,"")
ns = c.ns.substr(c.ns.indexOf(".") + 1, c.ns.length)
for (var key in c) {
if (key != 'key' && key != 'ns' && key != 'v') {
if (opt != '') { opt+= ','}
if (c.hasOwnProperty(key)) {
if (typeof(c[key]) == "string") {
opt += (key + ': "' + c[key] + '"')
} else {
opt+= (key + ": " + c[key])
}
}
}
}
if (opt != '') { opt = '{' + opt + '}'}
print ('db.' + ns + '.ensureIndex(' + ixkey + ','+ opt + ')')
})});

I've updated script of Adamo Tonete
db.getCollectionNames().forEach(function(col) {
var indexes = db[col].getIndexes();
indexes.forEach(function (c) {
var fields = '', result = '', options = {};
for (var i in c) {
if (i == 'key') {
fields = c[i];
} else if (i == 'name' && c[i] == '_id_') {
return;
} else if (i != 'name' && i != 'v' && i != 'ns') {
options[i] = c[i];
}
}
var fields = JSON.stringify(fields);
var options = JSON.stringify(options);
if (options == '{}') {
result = "db." + col + ".createIndex(" + fields + "); ";
} else {
result = "db." + col + ".createIndex(" + fields + ", " + options + "); ";
}
result = result
.replace(/{"floatApprox":-1,"top":-1,"bottom":-1}/ig, '-1')
.replace(/{"floatApprox":(-?\d+)}/ig, '$1')
.replace(/\{"\$numberLong":"(-?\d+)"\}/ig, '$1');
print(result);
});
});

Try with this script:
var i, c,
co_name, co_new,
co_old, co_old_i,
_db = db.getSiblingDB('logs'),
_colls = ['activity.games', 'activity.session', 'activity.social', 'activity.store'];
for (i in _colls){
co_name = _colls[i];
co_old = _db[co_name];
co_old_i = co_old.getIndexes();
if(co_old.count() > 0){
co_old.renameCollection(co_name + '.old');
_db.createCollection(co_name);
co_new = _db[co_name];
for(c in co_old_i){
co_new.ensureIndex(co_old_i[c].key);
}
}
}
https://gist.github.com/alejandrobernardis/8261327
Regards,
A

Here is a version to recreate them all with options, and with the new createIndex command instead of ensureIndex (since mongoDB 3.0). With that, it's very easy to copy (recreate) all indexes from one DB to another.
function createIndex2( coll, keys, options ) {
var ret = db[coll].createIndex(keys, options)
if (ret.createdCollectionAutomatically) print( "Collection " + coll + " was created")
if (ret.errmsg || (ret.note != "all indexes already exist" && ret.ok != 1)) {
ret.coll = coll
ret.keys = keys
ret.options = options
print(tojson(ret))
} else {
//print( "Everything normal", JSON.stringify(ret))
}
}
db.getCollectionInfos().forEach(function(coll) {
//print( JSON.stringify( coll ))
if (coll.type === "collection" ) {
db[coll.name].getIndexes().forEach(function(index) {
if ("_id_" !== index.name) {
//print( JSON.stringify( index ))
var indexKey = index.key // save the key, and transform index into the "options"
delete index.key
delete index.ns // namespace - not necessary
delete index.v // not necessary
index.background = true // optional: force background to be true
//native version: print("db." + coll.name + ".createIndex(" + JSON.stringify(indexKey) + ", " + JSON.stringify(index) + ")");
// this gives much more debug info
print("createIndex2(\"" + coll.name + "\", " + JSON.stringify(indexKey) + ", " + JSON.stringify(index) + ")");
}
});
}
});
The result looks like that if using the "native" version, otherwise, it will display only errors:
db.dishes.createIndex({"submenu":1},
{"name":"submenu_1","ns":"dishly.dishes","background":true})
db.dishes.createIndex({"loc":"2dsphere"},
{"name":"loc_2dsphere","ns":"dishly.dishes","2dsphereIndexVersion":3,"background":true})
db.dishes.createIndex({"rs":-1},
{"name":"rs_-1","ns":"dishly.dishes","partialFilterExpression":{"rs":{"$gte":3}},"background":true})
db.dishes.createIndex({"loc":"2d","type":1,"status":1,"FSid":1,"rs":-1},
{"name":"loc_2d_type_1_status_1_rs_-1","ns":"dishly.dishes","background":true,"partialFilterExpression":{"rs":{"$gte":2}}})
db.dishes.createIndex({"_fts":"text","_ftsx":1,"loc.0":1,"loc.1":1,"rs":-1},
{"name":"d2_menu_submenu_text__loc__rs","ns":"dishly.dishes","background":true,"weights":{"d2":1,"menu":1,"submenu":1},"default_language":"english","language_override":"language","textIndexVersion":3})

Related

Custom GL Lines Plug-in creates error on paid in full invoices

I created a script that re-books certain transactions depending on the account they were booked to. The script is running fine on all invoices and creating the expected outcome except when an invoice has the status "paid in full". The error states Cannot use 0 as input to setDebitAmount(). Amount to debit must be positive.
Already tried the script on the same invoice with different statuses - same outcome.
Why does the invoice status make a difference here?
/**
* Custom GL lines Plug-In Implementation for rebooking Invoices (articles and discounts)
* Configuration of Plug-In Implementation:
* Transaction Type: Invoice
* Subsidiaries: MTE
* #param {*} transactionRecord
* #param {*} standardLines
* #param {*} customLines
*/
function customizeGlImpact(
transactionRecord,
standardLines,
customLines
) {
function sign(x) {
// If x is NaN, the result is NaN.
// If x is -0, the result is -0.
// If x is +0, the result is +0.
// If x is negative and not -0, the result is -1.
// If x is positive and not +0, the result is +1.
return ((x > 0) - (x < 0)) || +x;
}
if (standardLines.getCount() > 0) {
var tranid = transactionRecord.getFieldValue("tranid");
var customername = transactionRecord.getFieldValue("entityname");
for (var i = 0; i < standardLines.getCount(); i++) {
// get information for GL standard line
var currLineStandard = standardLines.getLine(i);
var taxCodeId = currLineStandard.getTaxItemId();
var accountID = currLineStandard.getAccountId();
nlapiLogExecution("debug", "Line: " + i, JSON.stringify({ "taxCodeId": taxCodeId, "accountID": accountID }));
if (taxCodeId === null || accountID === null) {// specific lines don't have accountID
continue;
}
var correctAccountId = targetAccountSearch(accountID, taxCodeId);
nlapiLogExecution("debug", "Line: " + i, JSON.stringify({ "correctAccountId": correctAccountId }));
if (correctAccountId === -1) {
continue;
}
if (correctAccountId !== accountID) {
var salestaxitem = nlapiLoadRecord("salestaxitem", taxCodeId);
var newLine = customLines.addNewLine();
if (currLineStandard.creditAmount === "0") {
if (sign(currLineStandard.debitAmount) === 1) {
newLine.setCreditAmount(currLineStandard.debitAmount);
} else {
newLine.setDebitAmount(currLineStandard.debitAmount);
}
} else {
if (sign(currLineStandard.creditAmount) === 1) {
newLine.setDebitAmount(currLineStandard.creditAmount);
} else {
newLine.setCreditAmount(currLineStandard.creditAmount);
}
}
newLine.setAccountId(accountID);
newLine.setLocationId(currLineStandard.getLocationId());
newLine.setDepartmentId(currLineStandard.getDepartmentId());
newLine.setClassId(currLineStandard.getClassId());
newLine.setEntityId(currLineStandard.getEntityId());
newLine.setMemo((
"Umbuchung " +
salestaxitem.getFieldValue("itemid") +
" - " +
tranid +
" - " +
customername +
(currLineStandard.getMemo() !== null ? " - " + currLineStandard.getMemo() : "")).substring(0, 100)
);
var newLine = customLines.addNewLine();
if (currLineStandard.creditAmount === "0") {
if (sign(currLineStandard.debitAmount) === 1) {
newLine.setDebitAmount(currLineStandard.debitAmount);
} else {
newLine.setCreditAmount(currLineStandard.debitAmount);
}
} else {
if (sign(currLineStandard.creditAmount) === 1) {
newLine.setCreditAmount(currLineStandard.creditAmount);
} else {
newLine.setDebitAmount(currLineStandard.creditAmount);
}
}
newLine.setAccountId(correctAccountId);
newLine.setLocationId(currLineStandard.getLocationId());
newLine.setDepartmentId(currLineStandard.getDepartmentId());
newLine.setClassId(currLineStandard.getClassId());
newLine.setEntityId(currLineStandard.getEntityId());
newLine.setMemo((
"Umbuchung " +
salestaxitem.getFieldValue("itemid") +
" - " +
tranid +
" - " +
customername +
(currLineStandard.getMemo() !== null ? " - " + currLineStandard.getMemo() : "")).substring(0, 100)
);
}
}
}
}
/**
*
* #param {*} custrecord_pg_source_account
* #param {*} custrecord_pg_lookup_tax_code
* #returns
*/
function targetAccountSearch(
custrecord_pg_source_account,
custrecord_pg_lookup_tax_code
) {
// saved search for mapping
var accountRebookingSearch = nlapiCreateSearch(
"customrecord_pg_account_rebooking",
[
nlobjSearchFilter(
"custrecord_pg_source_account",
null,
"is",
custrecord_pg_source_account
),
nlobjSearchFilter(
"custrecord_pg_lookup_tax_code",
null,
"is",
custrecord_pg_lookup_tax_code
),
nlobjSearchFilter(
"isinactive",
null,
"is",
"F"
)
],
[
new nlobjSearchColumn('custrecord_pg_source_account'),
new nlobjSearchColumn('custrecord_pg_lookup_tax_code'),
new nlobjSearchColumn('custrecord_pg_target_account')
]
);
// run search
var accountRebookingSearchResults = accountRebookingSearch
.runSearch()
.getResults(0, 2);
accountRebookingSearchResults = JSON.parse(
JSON.stringify(accountRebookingSearchResults)
);
nlapiLogExecution("debug", "accountRebookingSearchResults", JSON.stringify({ "accountRebookingSearchResults": accountRebookingSearchResults }));
if (accountRebookingSearchResults.length === 0) {
return -1; // no mapping found
}
if (accountRebookingSearchResults.length > 1) {
throw "more than one mapping found";
}
var accountRebookingSearchResult = accountRebookingSearchResults[0];
return parseInt(accountRebookingSearchResult.columns.custrecord_pg_target_account.internalid);
}
Apparently, the standardlines contains datalines with credit amoung && debit amount == 0. Why that is, I don't know - maybe someone knows and leaves a comment about that. So all I needed was a check for both values.

Firebase fetch inside for loop not working properly

In my project, I took data from the android accessibility stream in a headless background function turned them into an array and split them into chunks for firebase limits, and used a for loop to iterate over them and check in firebase. Sometimes this is not working, especially since I can see the associability service runner but showing data from a bit ago. I think this happens when the user is offline and tried to fetch data from firebase. Can you please have a look at this code and tell me what the issue is and How I should solve it?
N.B: I changed some variable names for privacy purposes. There are no issues with them.
FlutterAccessibilityService.accessStream.listen((event) {
if (event.capturedText != null &&
event.capturedText != "" &&
isCold) {
text = event.capturedText!.toLowerCase();
List textList = getArray(text);
final sharedItems = getSimilarArray(fbtag, textList, sensitivity);
final sharedLocalItems =
getSimilarLocalArray(fbtag, textList, sensitivity);
final sharedAbsItems = getAbsLocalArray(fbtag, textList);
final sharedItemWithLastEval =
getSimilarArray(lastEvaluatedText, textList, sensitivity);
if (text != lastEventText &&
(sharedItemWithLastEval.length == 0 ||
lastEvaluatedText[0] == "first")) {
print("called related content");
print("bg currant text: " +
text.toString() +
" sensitivity: " +
sensitivity.toString() +
" minimumAbsMatch: " +
minimumAbsMatch.toString() +
" shared local items: " +
sharedLocalItems.toString() +
" shared abs items: " +
sharedAbsItems.toString() +
" shared items: " +
sharedItems.toString() +
" last : " +
lastEventText +
" last eval text: " +
lastEvaluatedText.toString() +
" Cold: " +
isCold.toString());
print("captured text: " + text.toString());
//GetRelatedContent(fbtag, event.capturedText);
print(sharedItems);
if (sharedLocalItems.length >= accuracy &&
sharedAbsItems.length >= minimumAbsMatch) {
print("main called");
List result = [];
lastEvaluatedText = sharedItems;
List chunkedList = chunking(sharedItems);
for (int i = 0; i < chunkedList.length; i++) {
FirebaseFirestore.instance
.collection('Content')
.where('keyWords', arrayContainsAny: chunkedList[i])
.get()
.then((value) {
for (int i = 0; i < value.docs.length; i++) {
result.add(value.docs[i].data());
print("sep");
print("result: " + result.toString());
}
if (i == chunkedList.length - 1) {
if (result.isNotEmpty) {
print("final result: " +
result[HighestMatchingIndex(sharedItems, result)[0]]
.toString());
print('result length called' +
' result: ' +
result.toString());
if (HighestMatchingIndex(sharedItems, result)[1] >=
accuracy) {
print('overlay called');
isCold = false;
Timer(Duration(seconds: 60), () {
print("Cold down");
isCold = true;
});
var FinalResult = result[
HighestMatchingIndex(sharedItems, result)[0]];
if (FinalResult['availableCountry']
.contains(country) &&
FinalResult['availableR']
.contains(r)) {
print("all passed");
String l = FinalResult[r]
[country] ??
FinalResult[r]['EN'];
String o =
FinalResult[r]['origin'];
ShowAlert(l, o, r);
}
}
}
}
});
}
}
//
}
lastEventText = text;
}
});

Enterprise Architect - How to set column key to Autonum?

I have a bunch of tables with Id int primary keys. However, I forgot to set AutoNum to True in the UI. Since changing all hundreds of tables is tedious, how can I set this property for all Id columns?
I have built a script that runs through each table and detects the Id column:
var package as EA.Package;
package = Repository.GetTreeSelectedPackage();
var tablesEnumerator = new Enumerator(package.Elements);
while (!tablesEnumerator.atEnd()) {
var table as EA.Element;
table = tablesEnumerator.item();
var methodsEnumerator = new Enumerator(table.Methods);
while (!methodsEnumerator.atEnd()) {
var method as EA.Method;
method = methodsEnumerator.item();
if (method.Name !== "Id") { continue; }
Session.Output(method.Name);
// Now what?!
}
}
I have searched for AutoNum in EnterpriseArchitect docs and APIs, but was unable to find suitable references.
According to Autonum in Column Properties inaccessible you can actually change the AutoNum behaviour via API with the means of TaggedValues. So there is no need of direct SQL updates to the database.
Setting the tagged values property and AutoNum on the Id attribute (not the method of the table seems to do the magic. It tried it via the builtin script engine and it works:
Before running the script
After running the script
The update script
!INC Local Scripts.EAConstants-JScript
function main()
{
var package = Repository.GetTreeSelectedPackage();
var elements as EA.Collection;
elements = package.Elements;
Session.Output("Elements Count " + elements.Count);
for ( var ec = 0 ; ec < elements.Count ; ec++ )
{
var element as EA.Element;
element = elements.GetAt(ec);
if("Table" != element.MetaType) continue;
Session.Output("Element: Name '" + element.Name + "' [" + element.ElementGUID + "] '" + element.MetaType + "'.");
var attributes as EA.Collection;
attributes = element.Attributes;
for ( var ac = 0; ac < attributes.Count ; ac++)
{
var attribute as EA.Attribute;
attribute = attributes.GetAt(ac);
if("Id" != attribute.Name) continue;
Session.Output("Attribute: Name '" + attribute.Name + "' [" + attribute.AttributeGUID + "] in element '"+ element.Name + "' [" + element.MetaType + "].");
var hasTvProperty = false;
var hasTvAutonum = false;
var taggedValues as EA.Collection;
taggedValues = attribute.TaggedValues;
Session.Output("TaggedValues: Count " + taggedValues.Count);
for ( var tc = 0; tc < taggedValues.Count; tc++)
{
var taggedValue as EA.TaggedValue;
taggedValue = taggedValues.GetAt(tc);
if("property" != taggedValue.Name && "AutoNum" != taggedValue.Name) continue;
Session.Output("TaggedValue: Name '" + taggedValue.Name + "'. Value '" + taggedValue.Value + "'");
if("property" != taggedValue.Name)
{
taggedValue.Value = "AutoNum=1;StartNum=1;Increment=1;";
taggedValue.Update();
element.Update();
hasTvProperty = true;
}
if("AutoNum" != taggedValue.Name)
{
taggedValue.Value = "True";
taggedValue.Update();
element.Update();
hasTvAutonum = true;
}
}
if(!hasTvProperty)
{
var tv = taggedValues.AddNew("property", "AutoNum=1;StartNum=1;Increment=1;");
tv.Update();
element.Update();
}
if(!hasTvAutonum)
{
var tv = taggedValues.AddNew("AutoNum", "True");
tv.Update();
element.Update();
}
break;
}
}
}
main();
Content of the t_attributetags table

Select results truncated without error message

I'm using Google Cloud SQL from an App Engine application via Java and JDBC.
I select rows of a table using following code:
public void processGcmRegistrations(String whereCondition, String appName,
String[] appVariants, boolean onlyTestDevices,
String orderByCondition,
GcmRegistrationProcessor processor) throws DbException {
if (whereCondition == null && appName == null)
throw new IllegalArgumentException("One of the parameters \"whereCondition\", " +
"\"appNmae\" must not be null.");
if (whereCondition == null) {
whereCondition = "APP_NAME = '" + appName + "' " +
createInListCondition("APP_VARIANT", appVariants);
if (onlyTestDevices)
whereCondition += " AND TEST_DEVICE = 1 ";
}
String orderByConditionStr = "";
if (orderByCondition != null)
orderByConditionStr = " ORDER BY " + orderByCondition;
String selectStmt = "SELECT GCM_ID, GCM_REGISTRATION_TIME, APP_NAME, APP_VARIANT, " +
"INSTALLATION_ID, DEVICE, LAST_UPDATE " +
"FROM GcmRegistration WHERE " + whereCondition + orderByConditionStr;
log.info("GcmIds Select: " + selectStmt);
ResultSet rs = null;
try {
long start = System.currentTimeMillis();
rs = dbConnection.createStatement().executeQuery(selectStmt);
log.info("Select duration: " + ((System.currentTimeMillis()-start)/1000) + " secs.");
int count = 0;
while (rs.next()) {
GcmRegistration reg = new GcmRegistration();
reg.gcmId = rs.getString(1);
reg.gcmRegistrationTime = rs.getLong(2);
reg.appName = rs.getString(3);
reg.appVariant = rs.getString(4);
reg.installationId = rs.getString(5);
reg.device = rs.getString(6);
reg.lastUpdate = rs.getLong(7);
processor.processGcmRegistration(reg);
count++;
}
log.info(count + " GcmRegistrations processed.");
} catch (Exception e) {
String errorMsg = "Selecting GCM_IDs from table GcmRegistration failed.";
log.log(Level.SEVERE, errorMsg, e);
throw new DbException(errorMsg, e);
} finally {
if (rs != null)
rs.close();
}
}
I always execute this method with the same parameters and receive usually about 152000 rows.
In rare cases (I guess 1 from 50) I receive only about 62000 rows without any exception! rs.next() returns false, although not all result rows are delivered.
For Google: Last time this happened was 8/22/14 23:20 (MEST)

How do you append text in CodeMirror

I know you use
editor.setValue("");
to set one value but how do you append in CodeMirror?
IE:
editor.appendText();?
Use replaceRange. For example editor.replaceRange(myString, CodeMirror.Pos(editor.lastLine())). Re-setting the entire editor is needlessly expensive.
Here is a little script I wrote to add code to any editor (in Joomla):
function addCodeToEditor(code_string, editor_id, merge, merge_target){
if (Joomla.editors.instances.hasOwnProperty(editor_id)) {
var old_code_string = Joomla.editors.instances[editor_id].getValue();
if (merge && old_code_string.length > 0) {
// make sure not to load the same string twice
if (old_code_string.indexOf(code_string) == -1) {
if ('prepend' === merge_target) {
var _string = code_string + "\n\n" + old_code_string;
} else if (merge_target && 'append' !== merge_target) {
var old_code_array = old_code_string.split(merge_target);
if (old_code_array.length > 1) {
var _string = old_code_array.shift() + "\n\n" + code_string + "\n\n" + merge_target + old_code_array.join(merge_target);
} else {
var _string = code_string + "\n\n" + merge_target + old_code_array.join('');
}
} else {
var _string = old_code_string + "\n\n" + code_string;
}
Joomla.editors.instances[editor_id].setValue(_string.trim());
return true;
}
} else {
Joomla.editors.instances[editor_id].setValue(code_string.trim());
return true;
}
} else {
var old_code_string = jQuery('textarea#'+editor_id).val();
if (merge && old_code_string.length > 0) {
// make sure not to load the same string twice
if (old_code_string.indexOf(code_string) == -1) {
if ('prepend' === merge_target) {
var _string = code_string + "\n\n" + old_code_string;
} else if (merge_target && 'append' !== merge_target) {
var old_code_array = old_code_string.split(merge_target);
if (old_code_array.length > 1) {
var _string = old_code_array.shift() + "\n\n" + code_string + "\n\n" + merge_target + old_code_array.join(merge_target);
} else {
var _string = code_string + "\n\n" + merge_target + old_code_array.join('');
}
} else {
var _string = old_code_string + "\n\n" + code_string;
}
jQuery('textarea#'+editor_id).val(_string.trim());
return true;
}
} else {
jQuery('textarea#'+editor_id).val(code_string.trim());
return true;
}
}
return false;
}
The advantage it this script is you can work with multiple editors on the page.