使用MongoDB中的Spring Data MongoDB对存储为BigDecimal类型的数值进行排序

时间:2014-08-12 03:29:16

标签: mongodb sorting bigdecimal spring-data-mongodb

我正在使用教程(https://spring.io/guides/tutorials/data/2/)学习Spring Data MongoDB。 在本教程中,cost的类型是BigDecimal,如下所示,它在MongoDB中存储为“字符串”。 所以,当我试图通过成本字段按升序排序得到排序结果时,我得到了错误的结果。

我发现使用BigDecimal类是计算的最佳方法。 但是,如果我使用MongoDB中的Spring Data MongoDB将数字保存为BigDecimal类型, 它将保存为字符串类型 我将得到一个错误的排序结果,如本教程。

为了精确起见,我能做些什么来获得正确的数字排序结果? 你能帮我解决这个问题吗? 非常感谢你提前。

例如,

1> MenuItem类

@Document(collection = "menu")
public class MenuItem {
  @Id
  private String id;

  @Field("itemName")
  @Indexed
  private String name;
  private BigDecimal cost;

2 - ;创建MenuItem的实例

MenuItem item = new MenuItem();
item.setDescription("Peanutty Noodles, perfect for every occasion.");
item.setName("Yummy Noodles");
item.setCost(new BigDecimal("52.99"));


MenuItem item = new MenuItem();
item.setDescription("Rice, Egg Fried");
item.setName("Yummy Rice");
item.setCost(new BigDecimal("211.99")); 

3>排序结果

  

db.menu.find()排序({成本:1})。

{“_ id”:ObjectId(“53e982f0300475a4fbab8c32”),“_ class”:“com.yummynoodlebar.persistence.domain.MenuItem”,“itemName”:“Yummy Rice”,“description”:“Rice,Egg Fried” ,“成分”:[{“name”:“Egg”,“description”:“Chicken Eggs”},{“name”:“Rice”,“description”:“Straight White Rice”}],“cost”: “211.99”,“minutesToPrepare”:0}

{“_ id”:ObjectId(“53e982f0300475a4fbab8c33”),“_ class”:“com.yummynoodlebar.persistence.domain.MenuItem”,“itemName”:“Yummy Rice”,“description”:“Rice,Egg Fried” ,“成分”:[{“name”:“Egg”,“description”:“Chicken Eggs”},{“name”:“Rice”,“description”:“Straight White Rice”}],“cost”: “211.99”,“minutesToPrepare”:0}

{“_ id”:ObjectId(“53e982f0300475a4fbab8c2f”),“_ class”:“com.yummynoodlebar.persistence.domain.MenuItem”,“itemName”:“Yummy Noodles”,“description”:“Peanutty Noodles,非常适合每个场合。“,”成分“:[{”name“:”Peanuts“,”description“:”A Nut“},{”name“:”Egg“,”description“:”用于面条“}, {“name”:“Noodles”,“description”:“酥脆,可爱的面条”},“费用”:“52.99”,“minutesToPrepare”:0}

{“_ id”:ObjectId(“53e982f0300475a4fbab8c30”),“_ class”:“com.yummynoodlebar.persistence.domain.MenuItem”,“itemName”:“Yummy Noodles”,“description”:“Peanutty Noodles,非常适合每个场合。“,”成分“:[{”name“:”Peanuts“,”description“:”A Nut“},{”name“:”Egg“,”description“:”用于面条“}, {“name”:“Noodles”,“description”:“酥脆,可爱的面条”},“费用”:“52.99”,“minutesToPrepare”:0}

{“_ id”:ObjectId(“53e982f0300475a4fbab8c31”),“_ class”:“com.yummynoodlebar.persistence.domain.MenuItem”,“itemName”:“Yummy Noodles”,“description”:“Peanutty Noodles,非常适合每个场合。“,”成分“:[{”name“:”Egg“,”description“:”用于面条“},{”name“:”Peanuts“,”description“:”A Nut“}, {“name”:“Noodles”,“description”:“酥脆,可爱的面条”},“费用”:“52.99”,“minutesToPrepare”:0}

3 个答案:

答案 0 :(得分:1)

不幸的是,BigDecimal本身就是MongoDB的not supported。这就是我们默认将其转换为String的原因。

对于更多的数字处理,特别是在处理价格等时,我们通常建议改为存储双打,并将它们直接转换为BigDecimal s用于域对象中的算术运算。

答案 1 :(得分:1)

如果您正在处理Money - 并且“cost”看起来像那样 - 那么在代码中使用Money类。钱将带有金额和货币。 Money有方法可以将数量作为BigDecimal获取等等。在MongoDB中坚持这样丰富的形状:

{cost:{amt:21199,ccode:“USD”}}

所有相同货币的数字操作(eq,gt,lt等)都能正常工作。 而且你无论如何都无法在数据库中进行交叉货币比较,因为汇率是动态的。

http://www.moschetti.org/rants/mongomoney.html

答案 2 :(得分:1)

自版本 3.4 以来,MongoDB已添加对&#34; BigDecimal&#34;的支持。按新的十进制数据类型(decimal128)。但是,默认情况下,spring数据仍然将Java class Login extends React.Component { login(e) { e.preventDefault(); var user = ''; var pass = ''; user = this.state.username; pass = this.state.password; this.authenticate(user, pass); return; } async authenticate(username, password) { let _this = this; Api.login(username, password) .then(async response => {await response.json()}) .then(async response => { //My code }); } render() { let { username, password } = this.state; return ( <View > <TextField label='username' value={username} autoCapitalize= 'none' onChangeText={ (username) => this.setState({ username }) } /> <TextField label='password' value={password} secureTextEntry autoCapitalize= 'none' onChangeText={ (password) => this.setState({ password }) } style={{marginBottom: 10}} /> <TouchableOpacity style={styles.loginButtons} onPress={(e) => this.login(e)}> <Text style={styles.buttonText}> Login </Text> </TouchableOpacity> </View> ); } } 映射到MongoDB login(username, password) { let url = '/api/sessions'; return fetch(BASE_URL + url, { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ user: { email: username, password: password } }) });} (我想这是为了向后兼容)。好消息是可以通过在spring boot应用程序中注入BigDecimal来简单地覆盖默认映射,如下所示:

string

请检查this post for more detailed information and even a complete example