2 votes

Requête de collection séparée dans RavenDB Index (WHERE IN)

En utilisant RavenDB v4.2 ou supérieur, je veux configurer un index qui interroge une autre collection. En gros, reproduire une clause WHERE IN dans la partie mapping de l'index.

Les modèles ci-dessous représentent deux collections. Ici, chaque User a une collection d'identifiants de dispositifs :

class Device {
    public string Id { get; set; }
    public string Name { get; set; }
}

class User {
    public string Id { get; set; }
    public string BlogPostId { get; set; }
    public List<string> DeviceIds { get; set; } 
}

Considérons maintenant l'indice suivant comme un exemple de ce que j'essaie d'obtenir :

public class DeviceIndex : AbstractIndexCreationTask<Device, DeviceIndex.Result>
{
    public class Result
    {
        public string Id { get; set; }
        public string DeviceName { get; set; }
        public bool HasUser { get; set; }
        public int UserCount { get; set; }
    }
    public DeviceIndex()
    {
        Map = devices => from d in devices
                         select new Result
                         {
                             Id = d.Id,
                             DeviceName = d.Name,

                             HasUser = ... ?, // How to get this from Users collection?
                             UserCount = ... ? // same...

                         };

    }

Comment remplir le HasUser vrai/faux et UserCount propriétés dans cet index ? Par exemple, comment puis-je interroger la collection 'User' ici ?

Veuillez noter que cet exemple est sérieusement simplifié pour des raisons de brièveté. Je ne suis pas vraiment intéressé par les solutions de contournement, ni par la modification de la logique sous-jacente.

2voto

oiBio Points 106

Comme @Danielle l'a mentionné, vous devez utiliser un mutli-map-index et réduire le résultat. Voici un exemple de travail

public class DeviceIndex : AbstractMultiMapIndexCreationTask<DeviceIndex.Result>
    {
        public class Result
        {
            public string Id { get; set; }
            public string DeviceName { get; set; }
            public bool HasUser { get; set; }
            public int UserCount { get; set; }
        }
        public DeviceIndex()
        {
            AddMap<User>(users => from u in users
                                  from deviceId in u.DeviceIds
                                  let d = LoadDocument<Device>(deviceId)
                                select new Result
                                {
                                    Id = d.Id,
                                    HasUser = true,
                                    UserCount = 1,
                                    DeviceName = d.Name,
                                });
            AddMap<Device>(devices => from d in devices
                                      select new Result
                                      {
                                          Id = d.Id,
                                          HasUser = false,
                                          UserCount = 0,
                                          DeviceName = d.Name,
                                      });

            Reduce = results => from result in results
                                group result by new { result.Id } into g
                                select new Result
                                {
                                    Id = g.First().Id,
                                    DeviceName = g.First().DeviceName,
                                    HasUser = g.Any(e => e.HasUser),
                                    UserCount = g.Sum(e => e.UserCount),
                                };

        }
    }

et vous pouvez l'appeler comme ceci

var result = await _session.Query<DeviceIndex.Result, DeviceIndex>().ToListAsync();

0voto

Danielle Points 150

Si vous avez une liste d'utilisateurs dans le Dispositif classe
List<string> Users
une liste qui contient les identifiants des documents de l'échantillon Utilisateurs collection alors vous pourriez Indexez ces documents connexes.

Voir : https://demo.ravendb.net/demos/csharp/related-documents/index-related-documents

Ou faites le contraire,
Créez un index sur le Utilisateurs et d'indexer la collection Dispositif info


Sans changer les modèles actuels,
Vous pouvez créer un Index multi-cartes pour indexer les données de différentes collections.

https://ravendb.net/docs/article-page/4.2/csharp/indexes/multi-map-indexes

https://ravendb.net/docs/article-page/4.2/csharp/studio/database/indexes/create-multi-map-index

https://ravendb.net/learn/inside-ravendb-book/reader/4.0/10-static-indexes-and-other-advanced-options#querying-many-sources-at-once-with-multimap-indexes

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X