简体   繁体   中英

Selecting a BsonDocument with its array containing only last N elements using mongodb C# driver

i have a collection in MongoDB with BsonDocuments like this

messages: [
{
time: "0001-01-01T00:00:00Z",
room: "ROOM2",
receiver: "xxxxxxxxx@xxx.xxx",
receiverName: "xxxxxxxxx",
sender: "xxxxxxxxx@xxx.xxx",
senderName: "xxxxxxxxx",
message_text: "jl,hrdls"
},
{
time: "0001-01-01T00:00:00Z",
room: "ROOM2",
receiver: "xxxxxxxxx@xxx.xxx",
receiverName: "xxxxxxxxx",
sender: "xxxxxxxxx@xxx.xxx",
senderName: "xxxxxxxxx",
message_text: "hello world"
},
{
time: "0001-01-01T00:00:00Z",
room: "ROOM2",
receiver: "xxxxxxxxx@xxx.xxx",
receiverName: "XXXXXXXXX",
sender: "XXXXXXXX@xxx.xxx",
senderName: "XXXXX",
message_text: "hello world"
}
],
_id: 4,
email1: "xxxx@XXX.xxx",
email2: "xxxxxx@xxx.xxx"

now Using C# driver for MongoDB I want to select these documents such that the 'messages' array contains only last two elements...I cannot find any solution...can someone please suggest a way?

if you're happy with a workaround:

after selecting the right documents from your Mongo collection into a List - here named result

    var filter = Builders<Entity>.Filter.Eq("email1", "email@one.net");
    List<Entity> result = await msgs.Find(filter).ToListAsync();

you could loop through the result and keep the first two message entries only:

foreach (Entity item in result)
            {
                item.messages = item.messages.OrderByDescending(p => p.time).Take(2).ToList();
            }

where Entity is a type representing your model. Something like:

class Entity
    {
        public BsonObjectId _id { get; set; }
        public string email1 { get; set; }
        public string email2 { get; set; }
        public List<Message> messages { get; set; }

        public Entity()
        {
            messages = new List<Message>();
        }
    }

    class Message
    {
        public DateTime time { get; set; }
        public string room { get; set; }
        //...
        public string message_text { get; set; }
    }

You need to do a projection like this, to include only the fields that you want:

var query = collection.Find(filter).   // your filter
               Project<Document>(
               Builders<Document>.Projection
                                 .Include("messages.senderName")
                                 .Include("messages.message_text")
                                 .Include("email1")
                                 .Include("email2")
);

For this I think you need to have your entity declared with the [BsonElement("messages")] attribute.

Please let me know if this worked.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM