MongoDB自定义转换

时间:2018-02-16 07:56:53

标签: mongodb spring-boot spring-data-mongodb

在我的Spring Boot应用程序中,我试图从MongoDB数据库中检索位于某个区域的商店列表。这些商店以这种形式存在于数据库中:

{
   _id:ObjectId("5a0c6711fb3aac66aafe26c8")
   picture:"http://placehold.it/150x150"
   name:"Sonique"
   email:"leilaware@sonique.com"
   city:"Rabat"
   location:Object
      type:"Point"
      coordinates:Array
          0:-6.74938
          1:33.83436
}

正在检索商店的ShopEntity类是:

package com.hidden_founders.jobs.software_engineer_java.coding_challenge.shopfinder.tech_services.persistence;

import com.hidden_founders.jobs.software_engineer_java.coding_challenge.shopfinder.domain.model.Location;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "shops")
public class ShopEntity {

    @Id
    private ObjectId id;

    private String picture;
    private String name;
    private String email;
    private String city;
    private Location location;

    public ShopEntity() {}

    public ShopEntity(ObjectId id, String picture, String name, String email, String city, Location location) {
        this.id = id;
        this.picture = picture;
        this.name = name;
        this.email = email;
        this.city = city;
        this.location = location;
    }

    public ObjectId getId() {
        return id;
    }

    public void setId(ObjectId id) {
        this.id = id;
    }

    public String getPicture() {
        return picture;
    }

    public void setPicture(String picture) {
        this.picture = picture;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public Location getLocation() {
        return location;
    }

    public void setLocation(Location location) {
        this.location = location;
    }

    @Override
    public String toString() {
        return "Shop{\n" +
                "\tid: " + id + '\n' +
                "\tpicture: " + picture + '\n' +
                "\tname: " + name + '\n' +
                "\temail: " + email + '\n' +
                "\tcity: " + city + '\n' +
                "\tlocation: " + location + '\n' +
                '}';
    }
}

其中location类是一个简单的POJO:

package com.hidden_founders.jobs.software_engineer_java.coding_challenge.shopfinder.domain.model;

public class Location {
    private double latitude;
    private double longitude;

    public Location() {}

    public Location(double latitude, double longitude) {
        this.latitude = latitude;
        this.longitude = longitude;
    }

    public double getLatitude() {
        return latitude;
    }

    public double getLongitude() {
        return longitude;
    }

    @Override
    public String toString() {
        return "{ latitude: " + latitude + ", " +
                "longitude: " + longitude + " " +
                "}";
    }
}

为了将GeoJsonPoint位置属性转换为我的自定义Location对象,我已经制作了一个自定义转换器来处理这种情况:

package com.hidden_founders.jobs.software_engineer_java.coding_challenge.shopfinder.tech_services.persistence;

import com.hidden_founders.jobs.software_engineer_java.coding_challenge.shopfinder.domain.model.Location;

import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;

@ReadingConverter
public class GeoJsonPointToLocationConverter implements Converter<GeoJsonPoint, Location> {
    @Override
    public Location convert(GeoJsonPoint source) {
        Location location = new Location(source.getY(), source.getX());
        return location;
    }
}

然后我已将此转换器注册到mongo配置中,如下所示:

package com.hidden_founders.jobs.software_engineer_java.coding_challenge.shopfinder.tech_services.persistence;

import com.mongodb.Mongo;
import com.mongodb.MongoClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.core.convert.CustomConversions;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class MongoConfig extends AbstractMongoConfiguration {

    @Override
    protected String getDatabaseName() {
        return "shop_finder";
    }

    @Override
    public Mongo mongo() {
        return new MongoClient("127.0.0.1", 27017);
    }

    @Bean
    @Override
    public CustomConversions customConversions() {
        List<Converter<?, ?>> converters = new ArrayList<>();
        converters.add(new GeoJsonPointToLocationConverter());
        return new CustomConversions(converters);
    }
}

不幸的是,这不起作用,正在检索商店但是Location属性没有使用适当的坐标进行初始化:

Shop{
    id: 5a0c6b42fd3eb67969316d83
    picture: http://placehold.it/150x150
    name: Sonique
    email: leilaware@sonique.com
    city: Rabat
    location: { latitude: 0.0, longitude: 0.0 }
}

拜托,我做错了什么!

编辑:为了将持久层与其他层分离,我只是通过外观将实体作为域类公开,如下所示:

package com.hidden_founders.jobs.software_engineer_java.coding_challenge.shopfinder.tech_services.persistence;

import com.hidden_founders.jobs.software_engineer_java.coding_challenge.shopfinder.domain.model.Location;
import com.hidden_founders.jobs.software_engineer_java.coding_challenge.shopfinder.domain.model.Shop;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Circle;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@EnableMongoRepositories
@Service
public class MongoFacade {

    @Autowired
    private ShopsRepository shopsRepository;

    public List<Shop> findShopsWithin(double centerLatitude, double centerLongitude, double radiusInKm) {
        List<Shop> shops = new ArrayList<>();
        List<ShopEntity> shopEntities = shopsRepository.findByLocationWithin(new Circle(centerLongitude, centerLatitude, radiusInKm/111.12));
        for (ShopEntity shopEntity :
                shopEntities) {
            shops.add(new Shop(shopEntity.getPicture(), shopEntity.getName(), shopEntity.getEmail(), shopEntity.getCity(),
                    new Location(shopEntity.getLocation().getY(), shopEntity.getLocation().getX())));
        }

        return shops;
    }
}

1 个答案:

答案 0 :(得分:1)

未调用自定义转换的原因是因为,您在Convertity类中提到的类型(GeoJsonPoint)未在您的Entity(ShopEntity)类中使用。

只有在必须将数据库中的对象转换为您指定的实体类型时,Mongo才会调用您的转换器(ReadingConverter),并且在此过程中,如果它遇到您在转换中指定的类型类。