Mam bardzo dużą bibliotekę w środowisku SharePoint Online:> 3000 (zestawy dokumentów) w folderze głównym i ponad 7000 (zestawy dokumentów, foldery i dokumenty) łącznie. System oparty jest głównie na niestandardowym kodzie: C # CSOM.
Jeśli chodzi o wydajność, system odniósłby duże korzyści z odpytywania podzbiorów całego zestawu danych, a raczej całego 7000 elementów za każdym razem (moje obecne rozwiązanie ładuje partie 5000 elementów w ListItemCollection: w moim przypadku najpierw 5000, a następnie 2000, a następnie zapytania są wykonywane przez LINQ), szczególnie mając na uwadze, że niektóre operacje są bezpośrednio powiązane z określonymi widokami.
Próbuję wykonać poniższą implementację, jak znalazłem w komentarzu do innego wątku .
Microsoft.SharePoint.Client.List list = ctx.Web.Lists.GetByTitle(ListName); ctx.Load(list); ctx.ExecuteQuery(); Microsoft.SharePoint.Client.View view = list.Views.GetByTitle(viewName); ctx.Load(view); ctx.ExecuteQuery(); CamlQuery query = new CamlQuery(); query.ViewXml = view.ViewQuery; ListItemCollection items = list.GetItems(query); ctx.Load(items); ctx.ExecuteQuery();
Moim problemem jest to, że ListItemCollection jest zapełniana wszystkimi elementami z kolekcji głównej (3000), gdy wybrane widoki składają się z maksymalnie 60 elementów.
View.ViewQuery jest wypełniony tą wartością:
"<GroupBy Collapse=\"FALSE\" GroupLimit=\"30\"><FieldRef Name=\"CurrentStatus\" /></GroupBy><OrderBy><FieldRef Name=\"CurrentStatus\" Ascending=\"FALSE\" /><FieldRef Name=\"Stage\" /></OrderBy><Where><And><Eq><FieldRef Name=\"Stage\" /><Value Type=\"Text\">Confirm Container</Value></Eq><Eq><FieldRef Name=\"PastTransition\" /><Value Type=\"Boolean\">0</Value></Eq></And></Where>"
Czy powyższy kod powinien działać? Jeśli tak, co jest nie tak? Jeśli nie, jakie jest inne rozwiązanie, które daje to samo?
Komentarze
- Jak wygląda ViewQuery jak?
Odpowiedź
Czy wyciągasz CAML z widoku, ponieważ użytkownicy mogą aktualizować szczegóły filtru? Jeśli nie, prawdopodobnie lepszym sposobem jest ręczne ustawienie zapytania.
Spróbuj:
query.ViewXml ="<View Scope=\"Recursive\"><Query><Where><And><Eq><FieldRef Name=\"Stage\" /><Value Type=\"Text\">Confirm Container</Value></Eq><Eq><FieldRef Name=\"PastTransition\" /><Value Type=\"Boolean\">0</Value></Eq></And></Where></Query></View>"
Ponieważ Twoja lista to> 7 tys. pozycji, musisz również upewnić się, że jeden lub oba kolumn Stage i PastTransition są indeksowane. Może zależeć od tego, który z nich zwraca mniejszy podzbiór danych i w jakiej kolejności są one oceniane.
Może być też konieczne wykonanie „RecursiveAll” zamiast „Recursive”, w zależności od tego, czy chcesz / musisz zwrócić foldery. Wyświetl wyliczenie zakresu: https://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spviewscope.aspx
Powinno to spowodować wyświetlenie przefiltrowanej listy. Stamtąd Twój kod może wykonać dowolne grupowanie / porządkowanie zwracanych produktów.
Aktualizacja
Ponieważ szczegóły zapytania muszą być dynamicznie pobierane z istniejących widoków (zgodnie z Twoją opinią poniżej), możesz wyciągnąć zawartość z istniejącego widoku.ViewQuery i wstrzyknąć ją do widoku XML powyżej. Pozbędzie się to i pozwoli na uruchomienie zapytania na listach> 5k.
Zobacz kod Jurgena, aby uzyskać kompletne rozwiązanie.
Komentarze
- To działa w ten sposób. Czy to oznacza, że skonfigurowanie zapytania CAML i filtrowanie na kolumnach indeksowanych z przeszukiwalnym zestawem danych zawierającym więcej niż 5000 elementów nie ulegnie awarii, jeśli zwrócony wynik jest mniejszy niż 5000? Jest to obejście, ale nie rozwiązanie. Czy nie ma sposobu, aby uzyskać to z widoku? Chciałbym, aby kwerenda była dynamicznie tworzona z kilku widoków i nie musiała za każdym razem odtwarzać konfiguracji widoku w kwerendzie CAML, jeśli jest to oczywiście możliwe. To już bardzo dobry początek! Więc dziękuję dużo 🙂
- @JurgenCuschieri: Powinno działać dobrze, jeśli jest więcej niż 5 tys. elementów listy. Nie jestem pewien, czy ' w pełni rozumiem Twój przypadek użycia, ale jeśli chcesz dynamicznie wyciągać szczegóły filtrów z widoku (lub widoków), prawdopodobnie możesz to zrobić, zgrywając < zapytanie > część widoku ' s CAML i dynamiczne wstrzykiwanie go do < View Scrope = " Recusive " > < / Wyświetl >.
- Spróbuję ' i wrócę do Ciebie. Aby było to trochę jaśniejsze, mam system z wieloma różnymi zapytaniami. Zapytanie CAML służy do załadowania partii 5000 pozycji do zbioru pozycji listy. LINQ służy do wykonywania zapytań w wynikowych ListItemCollection. Nie trzeba dodawać, że operacja zwraca wynik długo. Każdy (lub prawie każdy) scenariusz jest teoretycznie powiązany z widokiem. co oznacza, że zestaw danych, które można przeszukiwać, można zminimalizować do tych samych wyników widoku. więc jeśli zapytanie caml może być automatycznie wypełniane z widoku ' zapytanie – ma to większy sens, nie?
- widoki definiują poszczególne etapy w firmie klienta ' proces biznesowy. te operacje zapytań CAML, które są używane specjalnie na etapie, mogą zatem używać tego samego zapytania co widok. Spowoduje to zawężenie zbioru danych, które można przeszukiwać, zamiast używania wszystkich pozycji z listy za każdym razem
- Świetnie! Cieszę się, że się udało. My, programiści SharePoint, musimy trzymać się razem … 🙂
Odpowiedź
Poniżej jest moje ostateczne rozwiązanie, na podstawie odpowiedzi @Jima Barntisha.
Microsoft.SharePoint.Client.List list = ctx.Web.Lists.GetByTitle(ListName); ctx.Load(list); ctx.ExecuteQuery(); Microsoft.SharePoint.Client.View view = list.Views.GetByTitle(viewName); ctx.Load(view); ctx.ExecuteQuery(); CamlQuery query = new CamlQuery(); query.ViewXml = view.ViewQuery; int pFrom = query.ViewXml.IndexOf("<Where>") + "<Where>".Length; int pTo = query.ViewXml.LastIndexOf("</Where>"); string whereClause = query.ViewXml.Substring(pFrom, pTo - pFrom); string queryStr = "<View Scope=\"Recursive\"><Query><Where>" + whereClause + "</Where></Query></View>"; query.ViewXml = queryStr; ListItemCollection items = list.GetItems(query); ctx.Load(items); ctx.ExecuteQuery();