Skip to main content

Indexing Compare-Exchange Values


Create sample compare-exchange items

Let’s create some sample documents and compare-exchange items to use in the examples below.
To learn about ALL the available methods for creating a compare-exchange item, see Create compare-exchange item.

// Create some hotel room DOCUMENTS with general info:
// ===================================================

using (var session = store.OpenSession())
{
for (int i = 215; i <= 217; i++)
{
var room = new HotelRoom
{
RoomNumber = $"R{i}",
Description = $"Description of room number R{i}"
};

session.Store(room, $"hotelRooms/R{i}");
}

session.SaveChanges();
}

Index compare-exchange values

  • This index maps the rooms in a hotel, as well as compare-exchange values representing the guests in those rooms.

  • Use method LoadCompareExchangeValue to load the current details of each room from the associated compare-exchange value.

public class Rooms_ByGuestsAndPaymentStatus : AbstractIndexCreationTask<HotelRoom>
{
// The index-fields
public class IndexEntry
{
public string RoomNumber;
public int? NumberOfGuests;
public boo? FullyPaid { get; set; }
}

public Rooms_ByGuestsAndPaymentStatus()
{
Map = HotelRooms => from room in HotelRooms
// Call method 'LoadCompareExchangeValue'
// to load the compare-exchange value by its key (room number)
let cmpXchgValue = LoadCompareExchangeValue<HotelRoomCurrentDetails>(room.RoomNumber)

// Define the index-fields
select new IndexEntry()
{
// Index content from the document:
RoomNumber = room.RoomNumber,

// Index content from the compare-exchange value:
NumberOfGuests = cmpXchgValue != null ? cmpXchgValue.CurrentNumberOfGuests : (int?)null,
FullyPaid = cmpXchgValue != null ? cmpXchgValue.FullyPaid : (bool?)null
};
}
}

Query the index

  • Using the index above, you can query for all rooms (room documents) that are occupied by a specific number of guests.
    The NumberOfGuests index-field, which is used in the query, contains the number of guests taken from the related compare-exchange value.

  • For example, you can find all vacant rooms (0 guests) or rooms occupied by any specific number of guests.

// When querying the index, 
// the session does not need to be opened in cluster-wide mode.
using (var session = store.OpenSession())
{
// Query for all vacant rooms (0 guests)
List<HotelRoom> vacantRooms = session
.Query<Rooms_ByGuestsAndPaymentStatus.IndexEntry, Rooms_ByGuestsAndPaymentStatus>()
// Index-field 'NumberOfGuests' contains the guest count for each room,
// taken from the compare-exchange item.
.Where(x => x.NumberOfGuests == 0)
.OfType<HotelRoom>()
.ToList();

// Using the sample data created above, Room R217 will be returned, since it has no guests.
}

Query the index and project compare-exchange values

  • In addition to querying index-fields that already contain information from the related compare-exchange value,
    you can also project fields from the compare-exchange value into the query results.

  • In the following query example, we retrieve all customers who haven't fully paid yet,
    and project their phone number from the compare-exchange value using RavenQuery.CmpXchg.

// The session does not need to be opened in cluster-wide mode
using (var session = store.OpenSession())
{
List<ProjectedCustomerDetails> phonesOfCustomersThatNeedToPay = session
.Query<Rooms_ByGuestsAndPaymentStatus.IndexEntry, Rooms_ByGuestsAndPaymentStatus>()
// Index-field 'FullyPaid' contains info from the compare-exchange item
.Where(x => x.FullyPaid == false && x.NumberOfGuests > 0)
// Project query results:
.Select(x => new ProjectedCustomerDetails
{
// Project content from the compare-exchange item:
// Call 'RavenQuery.CmpXchg' to load the compare-exchange value by its key.
CustomerPhone = RavenQuery.CmpXchg<HotelRoomCurrentDetails>(x.RoomNumber).CustomerPhone,
// Project content from the index-field:
RoomNumber = x.RoomNumber
})
.ToList();

// Using the sample data created above, customer from room R216 will be returned
// in the projected data, since they haven't fully paid yet.
}

Syntax


LoadCompareExchangeValue()

Load a compare exchange value in the LINQ index-definition by its key.

//Load one compare exchange value
T LoadCompareExchangeValue<T>(string key);

//Load multiple compare exchange values
T[] LoadCompareExchangeValue<T>(IEnumerable<string> keys);

cmpxchg()

Load a compare exchange value in the JavaScript index-definition by its key.

//Load one compare exchange value
cmpxchg(key);

ParameterTypeDescription
TobjectThe type of the compare-exchange item's value
keystringThe key of a particular compare exchange value.
keysIEnumerable<string>The keys of multiple compare exchange values.

RavenQuery.CmpXchg()

This method is used when querying the index with a LINQ query
and projecting fields from the compare-exchange value into the query results.

// Get a compare-exchange value by key.
public static T CmpXchg<T>(string key)