-
Notifications
You must be signed in to change notification settings - Fork 0
Migrations
Sealog does not yet have database migrations, and this has caused some grief when older versions of the database are not compatible.
Here are some notes from migrating from Sealog Alvin 0.9.0 to 1.0.12-rc.
Cruises need a cruise_vessel
specified, which is always the R/V Atlantis.
db.cruises.updateMany(
{ $or: [
{ "cruise_additional_meta.cruise_vessel": { $exists: false } },
{ "cruise_additional_meta.cruise_vessel": "" },
] },
{ $set: { "cruise_additional_meta.cruise_vessel" : "R/V Atlantis" } }
)
To reset the admin user password, compute the password:
python3 -c 'import bcrypt; print(bcrypt.hashpw(b"asdf", bcrypt.gensalt(10)))'
and insert it into the database with:
db.users.update({ username: "admin" }, { $set: { password: "<output of above command>" } })
On April 28, 2021 the cruise SKQ201918S had an error in which the cruise_pi
key was in the cruise structure rather than under cruise_additional_meta
.
db.cruises.update(
{ "cruise_pi": { $exists: true } },
{ $rename: { "cruise_pi" : "cruise_additional_meta.cruise_pi" } }
)
On upgrade to Sealog version 2.1.3 we saw database errors from cruise_additional_meta.cruise_name
being empty, perhaps due to this change 91a63c3062746da5f4f100027583e2e706232fc9 probably because cruiseSuccessResponse
includes a cruiseAdditionalMetaCreate
mapping.
db.cruises.updateMany(
{ $or: [
{ "cruise_additional_meta.cruise_name": { $exists: false } },
{ "cruise_additional_meta.cruise_name": "" },
] },
{ $set: { "cruise_additional_meta.cruise_name" : "Untitled Cruise" } }
)
We had a request to show "Local X/Y/Z" instead of "Alvin X/Y/Z" especially with Jason.
for (var d of ["x","y","z"]) {
db.event_aux_data.updateMany(
{ "data_array.data_name": "alvin_" + d },
{ $set: { "data_array.$.data_name" : "local_" + d } }
)
}
db.event_aux_data.updateMany(
{ "data_source": "vehicleRealtimeAlvinCoordData" },
{ $set: { "data_source" : "vehicleRealtimeLocalCoordData" } }
)
We needed to clean up duplicate identical vehicleRealtimeAlvinCoordData
entries. The following complex query aggregates aux_data
entries that have a common event_id
and removes all but one, provided they are equal.
db.event_aux_data.aggregate(
[
{
$match: {
"data_source": "vehicleRealtimeAlvinCoordData",
}
},
{
$group: {
_id: "$event_id",
ids: { $push: "$_id" },
contents: { $push: "$data_array" },
count: { $sum: 1 },
}
},
{
$match: {
count: { $gte: 2 }
}
},
],
{ allowDiskUse: true }
).forEach((dupes) => {
// Check that they are all equal before we even consider deleting anything
let allSame = dupes.contents.every((v) => JSON.stringify(v) === JSON.stringify(dupes.contents[0]));
if (!allSame) {
print("Event " + dupes._id + " has duplicates that don't match!");
return;
}
// Drop the duplicates
print(`Dropping ${dupes.count-1} duplicates from ${dupes._id}`);
db.event_aux_data.remove({
_id : {
$in: dupes.ids.slice(1),
}
});
});
// Merge local_x/y fields back into the vehicleRealtimeNavData auxdata record,
// deleting the old vehicleRealtimeLocalCoordData record.
//
// Also should do the same with vehicleReNavAlvinCoordData -> vehicleReNavData.
db.event_aux_data.aggregate(
[
{
$match: {
"data_source": {
$in: [
"alvinRealtimeNavData",
"vehicleRealtimeNavData",
"vehicleRealtimeAlvinCoordData",
"vehicleRealtimeLocalCoordData",
]
}
}
},
{
$group: {
_id: "$event_id",
auxdatas: { $push: "$$ROOT" }
}
}
],
{ allowDiskUse: true }
).forEach((group) => {
const nav = group.auxdatas.find((x) =>
[
"alvinRealtimeNavData",
"vehicleRealtimeNavData"
]
.includes(x.data_source)
);
const local = group.auxdatas.find((x) =>
[
"vehicleRealtimeAlvinCoordData",
"vehicleRealtimeLocalCoordData",
]
.includes(x.data_source)
);
// skip if not both found
if (!nav || !local)
return;
const local_x = (local.data_array.find((x) => ["alvin_x", "local_x"].includes(x.data_name)) || {}).data_value;
const local_y = (local.data_array.find((x) => ["alvin_y", "local_y"].includes(x.data_name)) || {}).data_value;
if (local_x === undefined || local_y === undefined)
return;
if (nav.data_array.findIndex((x) => ["local_x", "local_y", "alvin_x", "alvin_y"].includes(x.data_name)) !== -1) {
print("Realtime nav data already has local_x / local_y, skipping");
return;
}
const insertat = nav.data_array.findIndex((x) => x.data_name === "depth");
if (insertat === -1)
return;
nav.data_array.splice(insertat, 0, {
data_name: "local_y",
data_value: local_y,
data_uom: "meters",
});
nav.data_array.splice(insertat, 0, {
data_name: "local_x",
data_value: local_x,
data_uom: "meters",
});
db.event_aux_data.replaceOne({ _id: nav._id }, nav);
db.event_aux_data.deleteOne({ _id: local._id });
});