Используя команду Labix mgo API для MongoDB, я пытаюсь выполнить операцию инкремента в собранной коллекции. Я могу сделать это просто отлично в неподготовленной коллекции, используя обычную структуру mgo.Change, но когда я пытаюсь сделать это в собранной коллекции, я получаю ошибку: full shard key must be in update object for collection: db_name.collection_name
Усовершенствование для отложенного MongoDB с использованием mgo Error «полный ключ осколка должен находиться в объекте обновления для сбора: ...»
Исходный код, который работает на un -sharded коллекция выглядит следующим образом:
change := mgo.Change{
ReturnNew: true,
Upsert: true,
Update: bson.M{
"$setOnInsert": bson.M{
"ci": r.Ci,
"dt": r.Dt,
"zi": r.Zi,
},
"$inc": &data,
},
}
_, err := collection.Upsert(bson.M{"_id": id, "ci": r.Ci, "dt": r.Dt, "zi": r.Zi}, change); if err != nil {
log.Println("FAILURE", err)
}
Однако при переходе к sharded коллекции, sharded на ключевом {ci: 1, dt: 1, zi: 1}
я получаю ошибку, упомянутых выше.
В попытке отладки я попытался выяснить, что происходит за кулисами с помощью mgo, и попытался сделать вставку непосредственно в терминал mongo.
db.collection.update({ "_id" : "98364_2013-12-11", "ci" : "16326", "dt" : "2013-12-11", "zi" : "98364"}, {$setOnInsert: { "ci" : "16326", "dt" : "2013-12-11", "zi" : "98364"} , $inc: {test :1}}, { upsert: true });
Однако, это у меня отдельная ошибка: Can't modify shard key's value. field: ci: "16326" collection: db.collection
Это то, что я думаю, что я должен выяснить, как только я выяснить мою щёток ошибку, но мне кажется странным, что его бросает эту ошибку с $ setOnInsert, поскольку он не должен изменять значение, просто установите его на исходную вставку. Все ошибки исчезают, когда я вырезаю часть $ setOnInsert команды, но мне нужен способ убедиться, что эти значения установлены, потому что они будут важны в запросах, которые я пишу, чтобы вернуть данные.
Назад к моей основной проблеме: я обнаружил, что когда я переставлял порядок обновления и обновления документов при взаимодействии с терминалом MongoDB, я получил ошибку, которую получаю, когда я проходил через mgo, поэтому я попытался очень строго контролировать порядок документов, передаваемый в структурах mgo.Change путем переключения на bson.D:
change := bson.D{
{
"Update",
bson.D{
{"$setOnInsert", bson.D{
{"_id", id},
{"ci", r.Ci},
{"dt", r.Dt},
{"zi", r.Zi},
},
},
{"$inc", &data},
},
},
{
"Upsert",
true,
},
}
log.Println(change)
err := collection.Update(bson.D{{"_id", id},{ "ci", r.Ci},{ "dt", r.Dt}, {"zi", r.Zi}},change); if err != nil {
log.Println("FAILURE", err)
}
на данный момент, печати изменения объекта урожайности: [{Update [{$setOnInsert [{_id 11635_2013-12-11} {ci 3599} {dt 2013-12-11} {zi 11635}]} {$inc 0xc21dd9d8d0}]} {Upsert true}]
, которые я считаю, что именно то, что я должен переходите как объект изменения точно в правильном порядке в соответствии с Mongo's documentation, но я все равно получаю то же самое full shard key must be in update object for collection: db.collection
.
Я понимаю, что использование collection.Find({_id: ... }).Apply(change, ...)
является возможной альтернативой, и оно работает правильно, когда я его использовал, но при тестировании на незащищенных коллекциях я видел более высокую производительность (как в ~ 20 раз быстрее) с помощью Upsert (или Обновление), и скорость является абсолютно приоритетной, поскольку я имею дело с десятками тысяч событий в секунду.
Я добираюсь до такой степени, что чувствую, что я пробовал все, о чем я думаю, и хотел бы получить свежий набор глаз, пытаясь помочь мне разобраться в происходящем, поэтому любая помощь будет оценена по достоинству.