С небольшим поворотом на @capaj's post. Ниже приведен общий способ получения всех идентификаторов документов в виде списка строк. Обратите внимание на использование Advanced.LuceneQuery<T>(idPropertyName)
, SelectFields<T>(idPropertyName)
и GetProperty(idPropertyName)
, чтобы сделать вещи универсальными. По умолчанию предполагается, что "Id"
является действительным свойством на заданном <T>
(что должно быть в случае 99,999% времени). В случае, если у вас есть другое свойство, как ваш Id
, вы можете его передать.
public static List<string> getAllIds<T>(DocumentStore docDB, string idPropertyName = "Id") {
return getAllIdsFrom<T>(0, new List<string>(), docDB, idPropertyName);
}
public static List<string> getAllIdsFrom<T>(int startFrom, List<string> list, DocumentStore docDB, string idPropertyName) {
var allUsers = list;
using (var session = docDB.OpenSession())
{
int queryCount = 0;
int start = startFrom;
while (true)
{
var current = session.Advanced.LuceneQuery<T>().Take(1024).Skip(start).SelectFields<T>(idPropertyName).ToList();
queryCount += 1;
if (current.Count == 0)
break;
start += current.Count;
allUsers.AddRange(current.Select(t => (t.GetType().GetProperty(idPropertyName).GetValue(t, null)).ToString()));
if (queryCount >= 28)
{
return getAllIdsFrom<T>(start, allUsers, docDB, idPropertyName);
}
}
}
return allUsers;
}
Пример где/как я использую это при создании в RavenDb с PatchRequest
помощью сеанса BulkInsert
. В некоторых случаях у меня могут быть сотни тысяч документов и я не могу позволить себе загружать все документы в памяти, чтобы повторно повторить их снова для операции патча ... таким образом, загрузка только их идентификаторов строк, чтобы перейти в Patch
команда.
void PatchRavenDocs()
{
var store = new DocumentStore
{
Url = "http://localhost:8080",
DefaultDatabase = "SoMeDaTaBaSeNaMe"
};
store.Initialize();
// >>>here is where I get all the doc IDs for a given type<<<
var allIds = getAllIds<SoMeDoCuMeNtTyPe>(store);
// create a new patch to ADD a new int property to my documents
var patches = new[]{ new PatchRequest { Type = PatchCommandType.Set, Name = "SoMeNeWPrOpeRtY" ,Value = 0 }};
using (var s = store.BulkInsert()){
int cntr = 0;
Console.WriteLine("ID Count " + allIds.Count);
foreach(string id in allIds)
{
// apply the patch to my document
s.DatabaseCommands.Patch(id, patches);
// spit out a record every 2048 rows as a basic sanity check
if ((cntr++ % 2048) == 0)
Console.WriteLine(cntr + " " + id);
}
}
}
Надеюсь, это поможет. :)
Я вижу, что выше решение работает потому, что Total No. записей около 4000, поэтому никаких запросов не будет <30. Просто любопытно, как бы справиться с аналогичным сценарием, в котором Total no records> 30 * 1024, то есть если они более чем говорят 31k? – annantDev
@annantDev Вы можете отслеживать количество запросов, сделанных в сеансе. Как только он достигнет 30, удалите старый сеанс, создайте новый сеанс и продолжите чтение. –